summaryrefslogtreecommitdiff
path: root/deps/v8_inspector
diff options
context:
space:
mode:
authorAli Ijaz Sheikh <ofrobots@google.com>2016-05-28 22:17:12 -0700
committerJeremiah Senkpiel <fishrock123@rocketmail.com>2016-07-05 22:09:22 +0200
commit62105288d34a1e2b00c8bb4eb608cbda6b7bf20c (patch)
tree29f36c2b7b3d84a7b61477e64319210e4fca4240 /deps/v8_inspector
parent2a8bd35bac64691506c7c66ae131ac28793be18a (diff)
downloadnode-new-62105288d34a1e2b00c8bb4eb608cbda6b7bf20c.tar.gz
deps: import v8_inspector
Pick up v8 inspector from [1]. This is the standalone version of the devtools debug protocol. [1] https://github.com/pavelfeldman/v8_inspector/commit/e1bb206 PR-URL: https://github.com/nodejs/node/pull/6792 Reviewed-By: jasnell - James M Snell <jasnell@gmail.com> Reviewed-By: addaleax - Anna Henningsen <anna@addaleax.net> Reviewed-By: bnoordhuis - Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8_inspector')
-rw-r--r--deps/v8_inspector/.gitignore1
-rw-r--r--deps/v8_inspector/.gitmodules0
-rw-r--r--deps/v8_inspector/README.md2
-rw-r--r--deps/v8_inspector/deps/jinja2/.gitignore10
-rw-r--r--deps/v8_inspector/deps/jinja2/.travis.yml24
-rw-r--r--deps/v8_inspector/deps/jinja2/AUTHORS33
-rw-r--r--deps/v8_inspector/deps/jinja2/CHANGES375
-rw-r--r--deps/v8_inspector/deps/jinja2/LICENSE31
-rw-r--r--deps/v8_inspector/deps/jinja2/MANIFEST.in12
-rw-r--r--deps/v8_inspector/deps/jinja2/Makefile21
-rw-r--r--deps/v8_inspector/deps/jinja2/README.rst49
-rw-r--r--deps/v8_inspector/deps/jinja2/artwork/jinjalogo.svg132
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/Makefile118
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/_static/.ignore0
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/_static/jinja-small.pngbin0 -> 10484 bytes
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/_templates/sidebarintro.html20
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/_templates/sidebarlogo.html3
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/_themes/LICENSE37
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/_themes/README31
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/_themes/jinja/layout.html8
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/_themes/jinja/relations.html19
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/_themes/jinja/static/jinja.css_t396
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/_themes/jinja/theme.conf3
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/api.rst808
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/cache_extension.py56
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/changelog.rst3
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/conf.py160
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/contents.rst.inc23
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/extensions.rst346
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/faq.rst191
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/index.rst34
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/integration.rst101
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/intro.rst123
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/jinjaext.py194
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/jinjastyle.sty119
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/latexindex.rst6
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/logo.pdfbin0 -> 5677 bytes
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/sandbox.rst94
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/switching.rst226
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/templates.rst1509
-rw-r--r--deps/v8_inspector/deps/jinja2/docs/tricks.rst100
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/basic/cycle.py13
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/basic/debugger.py7
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/basic/inheritance.py12
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/basic/templates/broken.html6
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/basic/templates/subbroken.html3
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/basic/test.py27
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/basic/test_filter_and_linestatements.py25
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/basic/test_loop_filter.py12
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/basic/translate.py14
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/bench.py433
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/profile.py52
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/rwbench/django/_form.html1
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/rwbench/django/_input_field.html1
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/rwbench/django/_textarea.html1
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/rwbench/django/index.html29
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/rwbench/django/layout.html29
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/rwbench/djangoext.py135
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/rwbench/genshi/helpers.html12
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/rwbench/genshi/index.html41
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/rwbench/genshi/layout.html30
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/rwbench/jinja/helpers.html12
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/rwbench/jinja/index.html29
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/rwbench/jinja/layout.html29
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/rwbench/mako/helpers.html11
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/rwbench/mako/index.html31
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/rwbench/mako/layout.html30
-rw-r--r--deps/v8_inspector/deps/jinja2/examples/rwbench/rwbench.py112
-rw-r--r--deps/v8_inspector/deps/jinja2/ext/Vim/jinja.vim135
-rw-r--r--deps/v8_inspector/deps/jinja2/ext/django2jinja/django2jinja.py768
-rw-r--r--deps/v8_inspector/deps/jinja2/ext/django2jinja/example.py7
-rw-r--r--deps/v8_inspector/deps/jinja2/ext/django2jinja/templates/index.html58
-rw-r--r--deps/v8_inspector/deps/jinja2/ext/django2jinja/templates/layout.html4
-rw-r--r--deps/v8_inspector/deps/jinja2/ext/django2jinja/templates/subtemplate.html1
-rw-r--r--deps/v8_inspector/deps/jinja2/ext/djangojinja2.py86
-rw-r--r--deps/v8_inspector/deps/jinja2/ext/inlinegettext.py78
-rw-r--r--deps/v8_inspector/deps/jinja2/ext/jinja.el128
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/__init__.py70
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/_compat.py102
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/_stringdefs.py132
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/bccache.py362
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/compiler.py1686
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/constants.py32
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/debug.py350
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/defaults.py43
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/environment.py1213
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/exceptions.py146
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/ext.py636
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/filters.py996
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/lexer.py734
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/loaders.py481
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/meta.py103
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/nodes.py919
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/optimizer.py68
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/parser.py899
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/runtime.py667
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/sandbox.py367
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/tests.py173
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/utils.py531
-rw-r--r--deps/v8_inspector/deps/jinja2/jinja2/visitor.py87
-rwxr-xr-xdeps/v8_inspector/deps/jinja2/scripts/jinja2-debug.py43
-rw-r--r--deps/v8_inspector/deps/jinja2/scripts/make-release.py164
-rw-r--r--deps/v8_inspector/deps/jinja2/scripts/pylintrc301
-rw-r--r--deps/v8_inspector/deps/jinja2/setup.cfg8
-rw-r--r--deps/v8_inspector/deps/jinja2/setup.py77
-rw-r--r--deps/v8_inspector/deps/jinja2/tests/conftest.py74
-rw-r--r--deps/v8_inspector/deps/jinja2/tests/res/__init__.py0
-rw-r--r--deps/v8_inspector/deps/jinja2/tests/res/templates/broken.html3
-rw-r--r--deps/v8_inspector/deps/jinja2/tests/res/templates/foo/test.html1
-rw-r--r--deps/v8_inspector/deps/jinja2/tests/res/templates/syntaxerror.html4
-rw-r--r--deps/v8_inspector/deps/jinja2/tests/res/templates/test.html1
-rw-r--r--deps/v8_inspector/deps/jinja2/tests/test_api.py327
-rw-r--r--deps/v8_inspector/deps/jinja2/tests/test_bytecode_cache.py32
-rw-r--r--deps/v8_inspector/deps/jinja2/tests/test_core_tags.py337
-rw-r--r--deps/v8_inspector/deps/jinja2/tests/test_debug.py73
-rw-r--r--deps/v8_inspector/deps/jinja2/tests/test_ext.py467
-rw-r--r--deps/v8_inspector/deps/jinja2/tests/test_filters.py558
-rw-r--r--deps/v8_inspector/deps/jinja2/tests/test_imports.py148
-rw-r--r--deps/v8_inspector/deps/jinja2/tests/test_inheritance.py248
-rw-r--r--deps/v8_inspector/deps/jinja2/tests/test_lexnparse.py609
-rw-r--r--deps/v8_inspector/deps/jinja2/tests/test_loader.py220
-rw-r--r--deps/v8_inspector/deps/jinja2/tests/test_regression.py278
-rw-r--r--deps/v8_inspector/deps/jinja2/tests/test_security.py161
-rw-r--r--deps/v8_inspector/deps/jinja2/tests/test_tests.py104
-rw-r--r--deps/v8_inspector/deps/jinja2/tests/test_utils.py76
-rw-r--r--deps/v8_inspector/deps/jinja2/tox.ini9
-rw-r--r--deps/v8_inspector/deps/markupsafe/.gitignore10
-rw-r--r--deps/v8_inspector/deps/markupsafe/.travis.yml11
-rw-r--r--deps/v8_inspector/deps/markupsafe/AUTHORS13
-rw-r--r--deps/v8_inspector/deps/markupsafe/CHANGES48
-rw-r--r--deps/v8_inspector/deps/markupsafe/LICENSE33
-rw-r--r--deps/v8_inspector/deps/markupsafe/MANIFEST.in2
-rw-r--r--deps/v8_inspector/deps/markupsafe/Makefile7
-rw-r--r--deps/v8_inspector/deps/markupsafe/README.rst101
-rw-r--r--deps/v8_inspector/deps/markupsafe/bench/bench_basic.py5
-rw-r--r--deps/v8_inspector/deps/markupsafe/bench/bench_largestring.py6
-rw-r--r--deps/v8_inspector/deps/markupsafe/bench/bench_long_empty_string.py6
-rw-r--r--deps/v8_inspector/deps/markupsafe/bench/bench_long_suffix.py6
-rw-r--r--deps/v8_inspector/deps/markupsafe/bench/bench_short_empty_string.py5
-rw-r--r--deps/v8_inspector/deps/markupsafe/bench/runbench.py43
-rw-r--r--deps/v8_inspector/deps/markupsafe/markupsafe/__init__.py305
-rw-r--r--deps/v8_inspector/deps/markupsafe/markupsafe/_compat.py26
-rw-r--r--deps/v8_inspector/deps/markupsafe/markupsafe/_constants.py267
-rw-r--r--deps/v8_inspector/deps/markupsafe/markupsafe/_native.py46
-rw-r--r--deps/v8_inspector/deps/markupsafe/markupsafe/_speedups.c239
-rw-r--r--deps/v8_inspector/deps/markupsafe/markupsafe/tests.py207
-rw-r--r--deps/v8_inspector/deps/markupsafe/setup.py133
-rw-r--r--deps/v8_inspector/deps/markupsafe/tox.ini5
-rw-r--r--deps/v8_inspector/deps/wtf/README.md1
-rw-r--r--deps/v8_inspector/deps/wtf/wtf/Assertions.h40
-rw-r--r--deps/v8_inspector/deps/wtf/wtf/Compiler.h54
-rw-r--r--deps/v8_inspector/deps/wtf/wtf/PtrUtil.h275
-rw-r--r--deps/v8_inspector/devtools/Inspector-1.1.json3924
-rw-r--r--deps/v8_inspector/devtools/protocol.json5167
-rw-r--r--deps/v8_inspector/platform/PlatformExport.h66
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/Allocator.h22
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/Array.h137
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/Backend_cpp.template0
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/Backend_h.template78
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/CodeGenerator.py308
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/Collections.h14
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/CollectionsSTL.h253
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/CollectionsWTF.h193
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/Dispatcher_cpp.template365
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/Dispatcher_h.template65
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/ErrorSupport.cpp71
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/ErrorSupport.h37
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/FrontendChannel.h45
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/Frontend_cpp.template53
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/Frontend_h.template57
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/Maybe.h89
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/OWNERS5
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/Parser.cpp496
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/Parser.h22
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/ParserTest.cpp504
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/String16.h14
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/String16STL.cpp602
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/String16STL.h236
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/String16WTF.cpp47
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/String16WTF.h139
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/TypeBuilder_cpp.template130
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/TypeBuilder_h.template211
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/ValueConversions.cpp51
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/ValueConversions.h163
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/Values.cpp354
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/Values.h221
-rwxr-xr-xdeps/v8_inspector/platform/inspector_protocol/generate-inspector-protocol-version464
-rw-r--r--deps/v8_inspector/platform/inspector_protocol/protocol.gyp89
-rw-r--r--deps/v8_inspector/platform/v8_inspector/Atomics.h27
-rw-r--r--deps/v8_inspector/platform/v8_inspector/DebuggerScript.js705
-rw-r--r--deps/v8_inspector/platform/v8_inspector/InjectedScript.cpp538
-rw-r--r--deps/v8_inspector/platform/v8_inspector/InjectedScript.h176
-rw-r--r--deps/v8_inspector/platform/v8_inspector/InjectedScriptNative.cpp97
-rw-r--r--deps/v8_inspector/platform/v8_inspector/InjectedScriptNative.h44
-rw-r--r--deps/v8_inspector/platform/v8_inspector/InjectedScriptSource.js1222
-rw-r--r--deps/v8_inspector/platform/v8_inspector/InspectedContext.cpp88
-rw-r--r--deps/v8_inspector/platform/v8_inspector/InspectedContext.h64
-rw-r--r--deps/v8_inspector/platform/v8_inspector/InspectorWrapper.cpp70
-rw-r--r--deps/v8_inspector/platform/v8_inspector/InspectorWrapper.h88
-rw-r--r--deps/v8_inspector/platform/v8_inspector/JavaScriptCallFrame.cpp133
-rw-r--r--deps/v8_inspector/platform/v8_inspector/JavaScriptCallFrame.h75
-rw-r--r--deps/v8_inspector/platform/v8_inspector/OWNERS5
-rw-r--r--deps/v8_inspector/platform/v8_inspector/RemoteObjectId.cpp72
-rw-r--r--deps/v8_inspector/platform/v8_inspector/RemoteObjectId.h59
-rw-r--r--deps/v8_inspector/platform/v8_inspector/ScriptBreakpoint.h55
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8Compat.h28
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8Console.cpp730
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8Console.h71
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8DebuggerAgentImpl.cpp1455
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8DebuggerAgentImpl.h248
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8DebuggerImpl.cpp854
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8DebuggerImpl.h168
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8DebuggerScript.cpp104
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8DebuggerScript.h98
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8FunctionCall.cpp125
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8FunctionCall.h68
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8HeapProfilerAgentImpl.cpp409
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8HeapProfilerAgentImpl.h60
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8InjectedScriptHost.cpp286
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8InjectedScriptHost.h44
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8InspectorSessionImpl.cpp279
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8InspectorSessionImpl.h93
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8ProfilerAgentImpl.cpp302
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8ProfilerAgentImpl.h65
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8Regex.cpp93
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8Regex.h37
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8RuntimeAgentImpl.cpp437
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8RuntimeAgentImpl.h133
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8StackTraceImpl.cpp227
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8StackTraceImpl.h74
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8StringUtil.cpp280
-rw-r--r--deps/v8_inspector/platform/v8_inspector/V8StringUtil.h22
-rwxr-xr-xdeps/v8_inspector/platform/v8_inspector/build/rjsmin.py295
-rw-r--r--deps/v8_inspector/platform/v8_inspector/build/xxd.py28
-rw-r--r--deps/v8_inspector/platform/v8_inspector/debugger_script_externs.js556
-rw-r--r--deps/v8_inspector/platform/v8_inspector/injected_script_externs.js97
-rw-r--r--deps/v8_inspector/platform/v8_inspector/public/ConsoleAPITypes.h47
-rw-r--r--deps/v8_inspector/platform/v8_inspector/public/ConsoleTypes.h55
-rw-r--r--deps/v8_inspector/platform/v8_inspector/public/V8ContentSearchUtil.h26
-rw-r--r--deps/v8_inspector/platform/v8_inspector/public/V8ContextInfo.h42
-rw-r--r--deps/v8_inspector/platform/v8_inspector/public/V8Debugger.h65
-rw-r--r--deps/v8_inspector/platform/v8_inspector/public/V8DebuggerAgent.h24
-rw-r--r--deps/v8_inspector/platform/v8_inspector/public/V8DebuggerClient.h54
-rw-r--r--deps/v8_inspector/platform/v8_inspector/public/V8EventListenerInfo.h36
-rw-r--r--deps/v8_inspector/platform/v8_inspector/public/V8HeapProfilerAgent.h23
-rw-r--r--deps/v8_inspector/platform/v8_inspector/public/V8Inspector.cpp125
-rw-r--r--deps/v8_inspector/platform/v8_inspector/public/V8Inspector.h81
-rw-r--r--deps/v8_inspector/platform/v8_inspector/public/V8InspectorSession.h67
-rw-r--r--deps/v8_inspector/platform/v8_inspector/public/V8InspectorSessionClient.h28
-rw-r--r--deps/v8_inspector/platform/v8_inspector/public/V8ProfilerAgent.h22
-rw-r--r--deps/v8_inspector/platform/v8_inspector/public/V8RuntimeAgent.h23
-rw-r--r--deps/v8_inspector/platform/v8_inspector/public/V8StackTrace.h42
-rw-r--r--deps/v8_inspector/platform/v8_inspector/public/V8ToProtocolValue.h17
-rw-r--r--deps/v8_inspector/platform/v8_inspector/v8_inspector.gyp48
-rw-r--r--deps/v8_inspector/v8_inspector.gyp35
-rw-r--r--deps/v8_inspector/v8_inspector.gypi94
256 files changed, 51764 insertions, 0 deletions
diff --git a/deps/v8_inspector/.gitignore b/deps/v8_inspector/.gitignore
new file mode 100644
index 0000000000..2a6b83e201
--- /dev/null
+++ b/deps/v8_inspector/.gitignore
@@ -0,0 +1 @@
+platform/v8_inspector/build/rjsmin.pyc
diff --git a/deps/v8_inspector/.gitmodules b/deps/v8_inspector/.gitmodules
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/deps/v8_inspector/.gitmodules
diff --git a/deps/v8_inspector/README.md b/deps/v8_inspector/README.md
new file mode 100644
index 0000000000..9892f5fc81
--- /dev/null
+++ b/deps/v8_inspector/README.md
@@ -0,0 +1,2 @@
+# v8_inspector
+# v8_inspector
diff --git a/deps/v8_inspector/deps/jinja2/.gitignore b/deps/v8_inspector/deps/jinja2/.gitignore
new file mode 100644
index 0000000000..3ae1fa70b3
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/.gitignore
@@ -0,0 +1,10 @@
+*.so
+docs/_build
+*.pyc
+*.pyo
+*.egg-info
+*.egg
+build
+dist
+.DS_Store
+.tox
diff --git a/deps/v8_inspector/deps/jinja2/.travis.yml b/deps/v8_inspector/deps/jinja2/.travis.yml
new file mode 100644
index 0000000000..9cf4d8656f
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/.travis.yml
@@ -0,0 +1,24 @@
+language: python
+python:
+ - "2.6"
+ - "2.7"
+ - "3.3"
+ - "3.4"
+ - "3.5"
+ - "pypy"
+
+install:
+ - pip install tox
+script:
+ - tox -e \
+ $(echo $TRAVIS_PYTHON_VERSION | sed 's/^\([0-9]\)\.\([0-9]\).*/py\1\2/')
+
+notifications:
+ email: false
+ irc:
+ channels:
+ - "chat.freenode.net#pocoo"
+ on_success: change
+ on_failure: always
+ use_notice: true
+ skip_join: true
diff --git a/deps/v8_inspector/deps/jinja2/AUTHORS b/deps/v8_inspector/deps/jinja2/AUTHORS
new file mode 100644
index 0000000000..943f625f87
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/AUTHORS
@@ -0,0 +1,33 @@
+Jinja is written and maintained by the Jinja Team and various
+contributors:
+
+Lead Developer:
+
+- Armin Ronacher <armin.ronacher@active-4.com>
+
+Developers:
+
+- Christoph Hack
+- Georg Brandl
+
+Contributors:
+
+- Bryan McLemore
+- Mickaël Guérin <kael@crocobox.org>
+- Cameron Knight
+- Lawrence Journal-World.
+- David Cramer
+
+Patches and suggestions:
+
+- Ronny Pfannschmidt
+- Axel Böhm
+- Alexey Melchakov
+- Bryan McLemore
+- Clovis Fabricio (nosklo)
+- Cameron Knight
+- Peter van Dijk (Habbie)
+- Stefan Ebner
+- Rene Leonhardt
+- Thomas Waldmann
+- Cory Benfield (Lukasa)
diff --git a/deps/v8_inspector/deps/jinja2/CHANGES b/deps/v8_inspector/deps/jinja2/CHANGES
new file mode 100644
index 0000000000..4e5df26c99
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/CHANGES
@@ -0,0 +1,375 @@
+Jinja2 Changelog
+================
+
+Version 2.8.1
+-------------
+
+(unreleased bugfix release)
+
+- Fixed the `for_qs` flag for `urlencode`.
+
+Version 2.8
+-----------
+(codename Replacement, released on July 26th 2015)
+
+- Added `target` parameter to urlize function.
+- Added support for `followsymlinks` to the file system loader.
+- The truncate filter now counts the length.
+- Added equalto filter that helps with select filters.
+- Changed cache keys to use absolute file names if available
+ instead of load names.
+- Fixed loop length calculation for some iterators.
+- Changed how Jinja2 enforces strings to be native strings in
+ Python 2 to work when people break their default encoding.
+- Added :func:`make_logging_undefined` which returns an undefined
+ object that logs failures into a logger.
+- If unmarshalling of cached data fails the template will be
+ reloaded now.
+- Implemented a block ``set`` tag.
+- Default cache size was incrased to 400 from a low 50.
+- Fixed ``is number`` test to accept long integers in all Python versions.
+- Changed ``is number`` to accept Decimal as a number.
+- Added a check for default arguments followed by non-default arguments. This
+ change makes ``{% macro m(x, y=1, z) %}...{% endmacro %}`` a syntax error. The
+ previous behavior for this code was broken anyway (resulting in the default
+ value being applied to `y`).
+- Add ability to use custom subclasses of ``jinja2.compiler.CodeGenerator`` and
+ ``jinja2.runtime.Context`` by adding two new attributes to the environment
+ (`code_generator_class` and `context_class`) (pull request ``#404``).
+- added support for context/environment/evalctx decorator functions on
+ the finalize callback of the environment.
+- escape query strings for urlencode properly. Previously slashes were not
+ escaped in that place.
+- Add 'base' parameter to 'int' filter.
+
+Version 2.7.3
+-------------
+(bugfix release, released on June 6th 2014)
+
+- Security issue: Corrected the security fix for the cache folder. This
+ fix was provided by RedHat.
+
+Version 2.7.2
+-------------
+(bugfix release, released on January 10th 2014)
+
+- Prefix loader was not forwarding the locals properly to
+ inner loaders. This is now fixed.
+- Security issue: Changed the default folder for the filesystem cache to be
+ user specific and read and write protected on UNIX systems. See `Debian bug
+ 734747`_ for more information.
+
+.. _Debian bug 734747: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=734747
+
+Version 2.7.1
+-------------
+(bugfix release, released on August 7th 2013)
+
+- Fixed a bug with ``call_filter`` not working properly on environment
+ and context filters.
+- Fixed lack of Python 3 support for bytecode caches.
+- Reverted support for defining blocks in included templates as this
+ broke existing templates for users.
+- Fixed some warnings with hashing of undefineds and nodes if Python
+ is run with warnings for Python 3.
+- Added support for properly hashing undefined objects.
+- Fixed a bug with the title filter not working on already uppercase
+ strings.
+
+Version 2.7
+-----------
+(codename Translation, released on May 20th 2013)
+
+- Choice and prefix loaders now dispatch source and template lookup
+ separately in order to work in combination with module loaders as
+ advertised.
+- Fixed filesizeformat.
+- Added a non-silent option for babel extraction.
+- Added `urlencode` filter that automatically quotes values for
+ URL safe usage with utf-8 as only supported encoding. If applications
+ want to change this encoding they can override the filter.
+- Added `keep-trailing-newline` configuration to environments and
+ templates to optionally preserve the final trailing newline.
+- Accessing `last` on the loop context no longer causes the iterator
+ to be consumed into a list.
+- Python requirement changed: 2.6, 2.7 or >= 3.3 are required now,
+ supported by same source code, using the "six" compatibility library.
+- Allow `contextfunction` and other decorators to be applied to `__call__`.
+- Added support for changing from newline to different signs in the `wordwrap`
+ filter.
+- Added support for ignoring memcache errors silently.
+- Added support for keeping the trailing newline in templates.
+- Added finer grained support for stripping whitespace on the left side
+ of blocks.
+- Added `map`, `select`, `reject`, `selectattr` and `rejectattr`
+ filters.
+- Added support for `loop.depth` to figure out how deep inside a recursive
+ loop the code is.
+- Disabled py_compile for pypy and python 3.
+
+Version 2.6
+-----------
+(codename Convolution, released on July 24th 2011)
+
+- internal attributes now raise an internal attribute error now instead
+ of returning an undefined. This fixes problems when passing undefined
+ objects to Python semantics expecting APIs.
+- traceback support now works properly for PyPy. (Tested with 1.4)
+- implemented operator intercepting for sandboxed environments. This
+ allows application developers to disable builtin operators for better
+ security. (For instance limit the mathematical operators to actual
+ integers instead of longs)
+- groupby filter now supports dotted notation for grouping by attributes
+ of attributes.
+- scoped blocks now properly treat toplevel assignments and imports.
+ Previously an import suddenly "disappeared" in a scoped block.
+- automatically detect newer Python interpreter versions before loading code
+ from bytecode caches to prevent segfaults on invalid opcodes. The segfault
+ in earlier Jinja2 versions here was not a Jinja2 bug but a limitation in
+ the underlying Python interpreter. If you notice Jinja2 segfaulting in
+ earlier versions after an upgrade of the Python interpreter you don't have
+ to upgrade, it's enough to flush the bytecode cache. This just no longer
+ makes this necessary, Jinja2 will automatically detect these cases now.
+- the sum filter can now sum up values by attribute. This is a backwards
+ incompatible change. The argument to the filter previously was the
+ optional starting index which defaultes to zero. This now became the
+ second argument to the function because it's rarely used.
+- like sum, sort now also makes it possible to order items by attribute.
+- like sum and sort, join now also is able to join attributes of objects
+ as string.
+- the internal eval context now has a reference to the environment.
+- added a mapping test to see if an object is a dict or an object with
+ a similar interface.
+
+Version 2.5.5
+-------------
+(re-release of 2.5.4 with built documentation removed for filesize.
+ Released on October 18th 2010)
+
+- built documentation is no longer part of release.
+
+Version 2.5.4
+-------------
+(bugfix release, released on October 17th 2010)
+
+- Fixed extensions not loading properly with overlays.
+- Work around a bug in cpython for the debugger that causes segfaults
+ on 64bit big-endian architectures.
+
+Version 2.5.3
+-------------
+(bugfix release, released on October 17th 2010)
+
+- fixed an operator precedence error introduced in 2.5.2. Statements
+ like "-foo.bar" had their implicit parentheses applied around the
+ first part of the expression ("(-foo).bar") instead of the more
+ correct "-(foo.bar)".
+
+Version 2.5.2
+-------------
+(bugfix release, released on August 18th 2010)
+
+- improved setup.py script to better work with assumptions people
+ might still have from it (``--with-speedups``).
+- fixed a packaging error that excluded the new debug support.
+
+Version 2.5.1
+-------------
+(bugfix release, released on August 17th 2010)
+
+- StopIteration exceptions raised by functions called from templates
+ are now intercepted and converted to undefineds. This solves a
+ lot of debugging grief. (StopIteration is used internally to
+ abort template execution)
+- improved performance of macro calls slightly.
+- babel extraction can now properly extract newstyle gettext calls.
+- using the variable `num` in newstyle gettext for something else
+ than the pluralize count will no longer raise a :exc:`KeyError`.
+- removed builtin markup class and switched to markupsafe. For backwards
+ compatibility the pure Python implementation still exists but is
+ pulled from markupsafe by the Jinja2 developers. The debug support
+ went into a separate feature called "debugsupport" and is disabled
+ by default because it is only relevant for Python 2.4
+- fixed an issue with unary operators having the wrong precendence.
+
+Version 2.5
+-----------
+(codename Incoherence, relased on May 29th 2010)
+
+- improved the sort filter (should have worked like this for a
+ long time) by adding support for case insensitive searches.
+- fixed a bug for getattribute constant folding.
+- support for newstyle gettext translations which result in a
+ nicer in-template user interface and more consistent
+ catalogs. (:ref:`newstyle-gettext`)
+- it's now possible to register extensions after an environment
+ was created.
+
+Version 2.4.1
+-------------
+(bugfix release, released on April 20th 2010)
+
+- fixed an error reporting bug for undefineds.
+
+Version 2.4
+-----------
+(codename Correlation, released on April 13th 2010)
+
+- the environment template loading functions now transparently
+ pass through a template object if it was passed to it. This
+ makes it possible to import or extend from a template object
+ that was passed to the template.
+- added a :class:`ModuleLoader` that can load templates from
+ precompiled sources. The environment now features a method
+ to compile the templates from a configured loader into a zip
+ file or folder.
+- the _speedups C extension now supports Python 3.
+- added support for autoescaping toggling sections and support
+ for evaluation contexts (:ref:`eval-context`).
+- extensions have a priority now.
+
+Version 2.3.1
+-------------
+(bugfix release, released on February 19th 2010)
+
+- fixed an error reporting bug on all python versions
+- fixed an error reporting bug on Python 2.4
+
+Version 2.3
+-----------
+(3000 Pythons, released on February 10th 2010)
+
+- fixes issue with code generator that causes unbound variables
+ to be generated if set was used in if-blocks and other small
+ identifier problems.
+- include tags are now able to select between multiple templates
+ and take the first that exists, if a list of templates is
+ given.
+- fixed a problem with having call blocks in outer scopes that
+ have an argument that is also used as local variable in an
+ inner frame (#360).
+- greatly improved error message reporting (#339)
+- implicit tuple expressions can no longer be totally empty.
+ This change makes ``{% if %}...{% endif %}`` a syntax error
+ now. (#364)
+- added support for translator comments if extracted via babel.
+- added with-statement extension.
+- experimental Python 3 support.
+
+Version 2.2.1
+-------------
+(bugfix release, released on September 14th 2009)
+
+- fixes some smaller problems for Jinja2 on Jython.
+
+Version 2.2
+-----------
+(codename Kong, released on September 13th 2009)
+
+- Include statements can now be marked with ``ignore missing`` to skip
+ non existing templates.
+- Priority of `not` raised. It's now possible to write `not foo in bar`
+ as an alias to `foo not in bar` like in python. Previously the grammar
+ required parentheses (`not (foo in bar)`) which was odd.
+- Fixed a bug that caused syntax errors when defining macros or using the
+ `{% call %}` tag inside loops.
+- Fixed a bug in the parser that made ``{{ foo[1, 2] }}`` impossible.
+- Made it possible to refer to names from outer scopes in included templates
+ that were unused in the callers frame (#327)
+- Fixed a bug that caused internal errors if names where used as iteration
+ variable and regular variable *after* the loop if that variable was unused
+ *before* the loop. (#331)
+- Added support for optional `scoped` modifier to blocks.
+- Added support for line-comments.
+- Added the `meta` module.
+- Renamed (undocumented) attribute "overlay" to "overlayed" on the
+ environment because it was clashing with a method of the same name.
+- speedup extension is now disabled by default.
+
+Version 2.1.1
+-------------
+(Bugfix release)
+
+- Fixed a translation error caused by looping over empty recursive loops.
+
+Version 2.1
+-----------
+(codename Yasuzō, released on November 23rd 2008)
+
+- fixed a bug with nested loops and the special loop variable. Before the
+ change an inner loop overwrote the loop variable from the outer one after
+ iteration.
+
+- fixed a bug with the i18n extension that caused the explicit pluralization
+ block to look up the wrong variable.
+
+- fixed a limitation in the lexer that made ``{{ foo.0.0 }}`` impossible.
+
+- index based subscribing of variables with a constant value returns an
+ undefined object now instead of raising an index error. This was a bug
+ caused by eager optimizing.
+
+- the i18n extension looks up `foo.ugettext` now followed by `foo.gettext`
+ if an translations object is installed. This makes dealing with custom
+ translations classes easier.
+
+- fixed a confusing behavior with conditional extending. loops were partially
+ executed under some conditions even though they were not part of a visible
+ area.
+
+- added `sort` filter that works like `dictsort` but for arbitrary sequences.
+
+- fixed a bug with empty statements in macros.
+
+- implemented a bytecode cache system. (:ref:`bytecode-cache`)
+
+- the template context is now weakref-able
+
+- inclusions and imports "with context" forward all variables now, not only
+ the initial context.
+
+- added a cycle helper called `cycler`.
+
+- added a joining helper called `joiner`.
+
+- added a `compile_expression` method to the environment that allows compiling
+ of Jinja expressions into callable Python objects.
+
+- fixed an escaping bug in urlize
+
+Version 2.0
+-----------
+(codename jinjavitus, released on July 17th 2008)
+
+- the subscribing of objects (looking up attributes and items) changed from
+ slightly. It's now possible to give attributes or items a higher priority
+ by either using dot-notation lookup or the bracket syntax. This also
+ changed the AST slightly. `Subscript` is gone and was replaced with
+ :class:`~jinja2.nodes.Getitem` and :class:`~jinja2.nodes.Getattr`.
+
+ For more information see :ref:`the implementation details <notes-on-subscriptions>`.
+
+- added support for preprocessing and token stream filtering for extensions.
+ This would allow extensions to allow simplified gettext calls in template
+ data and something similar.
+
+- added :meth:`jinja2.environment.TemplateStream.dump`.
+
+- added missing support for implicit string literal concatenation.
+ ``{{ "foo" "bar" }}`` is equivalent to ``{{ "foobar" }}``
+
+- `else` is optional for conditional expressions. If not given it evaluates
+ to `false`.
+
+- improved error reporting for undefined values by providing a position.
+
+- `filesizeformat` filter uses decimal prefixes now per default and can be
+ set to binary mode with the second parameter.
+
+- fixed bug in finalizer
+
+Version 2.0rc1
+--------------
+(no codename, released on June 9th 2008)
+
+- first release of Jinja2
diff --git a/deps/v8_inspector/deps/jinja2/LICENSE b/deps/v8_inspector/deps/jinja2/LICENSE
new file mode 100644
index 0000000000..31bf900e58
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/LICENSE
@@ -0,0 +1,31 @@
+Copyright (c) 2009 by the Jinja Team, see AUTHORS for more details.
+
+Some rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+ * The names of the contributors may not be used to endorse or
+ promote products derived from this software without specific
+ prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/deps/v8_inspector/deps/jinja2/MANIFEST.in b/deps/v8_inspector/deps/jinja2/MANIFEST.in
new file mode 100644
index 0000000000..0d6db7c5ed
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/MANIFEST.in
@@ -0,0 +1,12 @@
+include MANIFEST.in Makefile CHANGES LICENSE AUTHORS run-tests.py
+recursive-include docs *
+recursive-include custom_fixers *
+recursive-include ext *
+recursive-include artwork *
+recursive-include examples *
+recursive-include jinja2/testsuite/res *
+recursive-exclude docs/_build *
+recursive-exclude jinja2 *.pyc
+recursive-exclude docs *.pyc
+recursive-exclude jinja2 *.pyo
+recursive-exclude docs *.pyo
diff --git a/deps/v8_inspector/deps/jinja2/Makefile b/deps/v8_inspector/deps/jinja2/Makefile
new file mode 100644
index 0000000000..aadaaa9431
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/Makefile
@@ -0,0 +1,21 @@
+test:
+ py.test
+
+develop:
+ pip install --editable .
+
+tox-test:
+ @tox
+
+release:
+ python scripts/make-release.py
+
+upload-docs:
+ $(MAKE) -C docs html dirhtml latex
+ $(MAKE) -C docs/_build/latex all-pdf
+ cd docs/_build/; mv html jinja-docs; zip -r jinja-docs.zip jinja-docs; mv jinja-docs html
+ scp -r docs/_build/dirhtml/* flow.srv.pocoo.org:/srv/websites/jinja.pocoo.org/docs/
+ scp -r docs/_build/latex/Jinja2.pdf flow.srv.pocoo.org:/srv/websites/jinja.pocoo.org/docs/jinja-docs.pdf
+ scp -r docs/_build/jinja-docs.zip flow.srv.pocoo.org:/srv/websites/jinja.pocoo.org/docs/
+
+.PHONY: test
diff --git a/deps/v8_inspector/deps/jinja2/README.rst b/deps/v8_inspector/deps/jinja2/README.rst
new file mode 100644
index 0000000000..0684e8a1b2
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/README.rst
@@ -0,0 +1,49 @@
+Jinja2
+~~~~~~
+
+Jinja2 is a template engine written in pure Python. It provides a
+`Django`_ inspired non-XML syntax but supports inline expressions and
+an optional `sandboxed`_ environment.
+
+Nutshell
+--------
+
+Here a small example of a Jinja template::
+
+ {% extends 'base.html' %}
+ {% block title %}Memberlist{% endblock %}
+ {% block content %}
+ <ul>
+ {% for user in users %}
+ <li><a href="{{ user.url }}">{{ user.username }}</a></li>
+ {% endfor %}
+ </ul>
+ {% endblock %}
+
+Philosophy
+----------
+
+Application logic is for the controller, but don't make the template designer's
+life difficult by restricting functionality too much.
+
+For more information visit the new `Jinja2 webpage`_ and `documentation`_.
+
+The `Jinja2 tip`_ is installable via `easy_install` with ``easy_install
+Jinja2==dev``.
+
+.. _sandboxed: http://en.wikipedia.org/wiki/Sandbox_(computer_security)
+.. _Django: http://www.djangoproject.com/
+.. _Jinja2 webpage: http://jinja.pocoo.org/
+.. _documentation: http://jinja.pocoo.org/docs/
+.. _Jinja2 tip: http://jinja.pocoo.org/docs/intro/#as-a-python-egg-via-easy-install
+
+Builds
+------
+
++---------------------+------------------------------------------------------------------------------+
+| ``master`` | .. image:: https://travis-ci.org/mitsuhiko/jinja2.svg?branch=master |
+| | :target: https://travis-ci.org/mitsuhiko/jinja2 |
++---------------------+------------------------------------------------------------------------------+
+| ``2.7-maintenance`` | .. image:: https://travis-ci.org/mitsuhiko/jinja2.svg?branch=2.7-maintenance |
+| | :target: https://travis-ci.org/mitsuhiko/jinja2 |
++---------------------+------------------------------------------------------------------------------+
diff --git a/deps/v8_inspector/deps/jinja2/artwork/jinjalogo.svg b/deps/v8_inspector/deps/jinja2/artwork/jinjalogo.svg
new file mode 100644
index 0000000000..0bc9ea4e8b
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/artwork/jinjalogo.svg
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="300"
+ height="120"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.45.1"
+ version="1.0"
+ sodipodi:docbase="/Users/mitsuhiko/Development/jinja2/artwork"
+ sodipodi:docname="jinjalogo.svg"
+ inkscape:export-filename="/Users/mitsuhiko/Development/jinja2/docs/_static/jinjabanner.png"
+ inkscape:export-xdpi="60"
+ inkscape:export-ydpi="60"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs
+ id="defs4">
+ <linearGradient
+ id="linearGradient6558">
+ <stop
+ style="stop-color:#575757;stop-opacity:1;"
+ offset="0"
+ id="stop6560" />
+ <stop
+ style="stop-color:#2f2f2f;stop-opacity:1;"
+ offset="1"
+ id="stop6562" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6558"
+ id="radialGradient6564"
+ cx="61.297766"
+ cy="60.910986"
+ fx="61.297766"
+ fy="60.910986"
+ r="44.688254"
+ gradientTransform="matrix(1,0,0,0.945104,0,3.343747)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6558"
+ id="radialGradient6580"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.945104,0.355158,3.334402)"
+ cx="61.297766"
+ cy="60.910986"
+ fx="61.297766"
+ fy="60.910986"
+ r="44.688254" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6558"
+ id="linearGradient4173"
+ x1="255.15521"
+ y1="32.347946"
+ x2="279.8912"
+ y2="32.347946"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8073249,0,0,0.8073249,57.960878,7.4036303)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6558"
+ id="linearGradient5145"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7902775,0,0,0.82474,60.019977,8.0684132)"
+ x1="255.15521"
+ y1="32.347946"
+ x2="279.8912"
+ y2="32.347946" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.8"
+ inkscape:cx="137.4752"
+ inkscape:cy="57.574575"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ width="300px"
+ height="120px"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:window-width="1396"
+ inkscape:window-height="900"
+ inkscape:window-x="0"
+ inkscape:window-y="22" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:#f4f4f4;fill-opacity:1;stroke:#e7e7e7;stroke-width:0.8;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;font-family:Bitstream Vera Sans;stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 165.36463,80.874808 L 165.36463,80.874808 L 153.32556,80.874808 L 153.32556,81.8344 L 147.64994,81.8344 L 147.64994,36.035583 L 165.36463,36.035583 L 165.36463,20.333129 C 170.58154,21.031083 173.07533,22.077914 172.84609,23.473621 C 172.78871,24.055258 172.21545,24.549594 171.12624,24.956624 L 171.12624,36.035583 L 189.09895,36.035583 L 189.09895,82.532286 L 183.33733,82.532286 L 183.33733,80.874808 L 171.12624,80.874808 L 171.12624,102.94548 L 165.36463,102.94548 L 165.36463,80.874808 M 153.32556,55.489173 L 153.32556,55.489173 L 165.36463,55.489173 L 165.36463,41.793146 L 153.32556,41.793146 L 153.32556,55.489173 M 171.12624,55.489173 L 171.12624,55.489173 L 183.33733,55.489173 L 183.33733,41.793146 L 171.12624,41.793146 L 171.12624,55.489173 M 183.33733,61.333977 L 183.33733,61.333977 L 171.12624,61.333977 L 171.12624,75.030006 L 183.33733,75.030006 L 183.33733,61.333977 M 165.36463,61.333977 L 165.36463,61.333977 L 153.32556,61.333977 L 153.32556,75.030006 L 165.36463,75.030006 L 165.36463,61.333977 M 132.85897,59.414792 C 137.33069,63.136883 140.99969,67.934848 143.86618,73.808701 L 139.13654,77.385372 C 137.24467,72.965445 134.6362,69.12707 131.31114,65.87024 L 131.31114,102.94548 L 125.63554,102.94548 L 125.63554,68.57455 C 122.31042,71.947693 118.52671,74.913707 114.28436,77.47261 L 109.64069,73.372526 C 121.50782,67.091566 130.62312,55.489212 136.98668,38.565417 L 116.26221,38.565417 L 116.26221,32.720615 L 125.80754,32.720615 L 125.80754,20.333129 C 130.85245,21.031083 133.31761,22.048838 133.20299,23.386383 C 133.14561,24.026183 132.57235,24.549594 131.48307,24.956624 L 131.48307,32.720615 L 140.77043,32.720615 L 143.60824,36.733469 C 140.68444,45.51526 137.10137,53.075692 132.85897,59.414792 M 254.11016,49.469901 L 254.11016,49.469901 L 254.11016,20.333129 C 259.21243,21.031083 261.67755,22.048838 261.50562,23.386383 C 261.44823,23.909869 261.04699,24.346044 260.30172,24.694917 C 260.30164,24.694986 260.30164,24.694986 260.30172,24.694917 L 260.30172,24.694917 L 259.78578,24.956624 L 259.78578,49.469901 L 277.15652,49.469901 L 277.15652,55.227471 L 259.78578,55.227471 L 259.78578,93.785712 L 281.45616,93.785712 L 281.45616,99.63051 L 232.35378,99.63051 L 232.35378,93.785712 L 254.11016,93.785712 L 254.11016,55.227471 L 236.22346,55.227471 L 236.22346,49.469901 L 254.11016,49.469901 M 225.5603,59.327554 C 231.12111,63.107798 235.62145,67.876693 239.06127,73.634235 L 234.76157,77.647079 C 231.60845,72.180322 227.82475,67.934848 223.41044,64.910648 L 223.41044,102.94548 L 217.73484,102.94548 L 217.73484,67.44049 C 212.91919,71.627831 207.70222,75.030021 202.084,77.647079 L 197.87027,73.198053 C 212.66118,66.917101 224.01239,55.372897 231.92377,38.565417 L 205.35172,38.565417 L 205.35172,32.720615 L 217.99283,32.720615 L 217.99283,20.333129 C 223.03774,21.031083 225.50291,22.048838 225.38829,23.386383 C 225.33089,24.026183 224.75765,24.549594 223.66837,24.956624 L 223.66837,32.720615 L 236.22346,32.720615 L 238.80326,36.733469 C 235.13421,45.51526 230.71987,53.046611 225.5603,59.327554"
+ id="text4761" />
+ <path
+ style="font-size:44.09793472px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#b41717;fill-opacity:1;stroke:#7f2828;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Candara;stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 149.14708,37.774469 C 148.97807,41.117899 148.84526,44.824225 148.74871,48.893456 C 148.67626,52.962754 148.3818,70.641328 148.38184,75.524422 C 148.3818,79.065795 148.05588,81.991266 147.40406,84.300835 C 146.75219,86.610422 145.72612,88.557071 144.32585,90.140779 C 142.94969,91.724494 141.17522,92.901283 139.00239,93.671139 C 136.82953,94.440996 134.22211,94.825935 131.18014,94.825935 C 128.83828,94.825935 126.73787,94.59498 124.87889,94.133049 L 125.4221,89.31593 C 127.13623,90.0418 128.92278,90.404734 130.78177,90.404733 C 132.85805,90.404734 134.66875,90.140782 136.2139,89.612876 C 137.78315,89.062981 139.02651,88.216133 139.94396,87.072335 C 140.8855,85.928548 141.54942,84.520804 141.93572,82.8491 C 142.34613,81.177412 142.55134,78.988811 142.55136,76.283285 C 142.55134,66.297119 142.62852,44.659257 142.26641,37.774469 L 149.14708,37.774469 M 166.38498,80.732697 L 159.83024,80.732697 C 160.16821,76.333498 160.33723,71.307412 160.33723,65.654424 C 160.33723,59.2976 159.91471,53.963567 159.06973,49.652319 L 166.31257,48.761483 C 166.02284,53.358679 165.87799,58.98965 165.87799,65.654424 C 165.87799,70.933479 166.04699,75.959565 166.38498,80.732697 M 167.90601,39.490159 C 167.90598,40.611994 167.5076,41.590815 166.7109,42.42662 C 165.91418,43.240515 164.79155,43.647442 163.343,43.647399 C 162.11172,43.647442 161.146,43.295504 160.44588,42.591595 C 159.76988,41.865769 159.43188,40.996927 159.43188,39.98507 C 159.43188,38.885304 159.84231,37.928485 160.66315,37.114591 C 161.48399,36.30078 162.61869,35.893853 164.06727,35.893811 C 165.25023,35.893853 166.17975,36.256783 166.85575,36.982609 C 167.55588,37.686526 167.90598,38.522373 167.90601,39.490159 M 206.72748,80.732697 L 200.13651,80.732697 C 200.66763,74.947749 200.93319,68.634899 200.9332,61.794122 C 200.93319,58.406756 200.1727,56.097177 198.65174,54.865371 C 197.15487,53.61163 195.00619,52.984747 192.20564,52.984714 C 188.77731,52.984747 185.61465,54.117535 182.71753,56.383099 C 182.71753,63.883761 182.76583,72.000287 182.86238,80.732697 L 176.27142,80.732697 C 176.68182,73.254058 176.88707,67.843042 176.88707,64.499632 C 176.88707,59.352589 176.3559,54.359493 175.29363,49.520339 L 181.66734,48.695493 L 182.35539,52.720761 L 182.64511,52.720761 C 186.21823,49.773323 190.04483,48.299592 194.12499,48.299567 C 198.13265,48.299592 201.23499,49.113454 203.43201,50.741118 C 205.62895,52.346863 206.72747,55.217334 206.72748,59.352563 C 206.72747,59.770507 206.70331,60.595362 206.65507,61.827118 C 206.60675,63.058915 206.5826,63.883761 206.58262,64.30167 C 206.5826,67.975018 206.63088,73.452022 206.72748,80.732697 M 222.69791,48.695493 C 222.28747,55.514282 222.08225,62.355041 222.08225,69.21778 C 222.08225,71.043461 222.14262,73.463019 222.26332,76.476468 C 222.40822,79.467925 222.4806,81.502559 222.48063,82.580363 C 222.4806,89.685068 219.51105,93.996287 213.57195,95.514024 L 211.76124,93.006484 C 213.90995,91.356766 215.2378,89.597085 215.74478,87.727431 C 216.49321,85.043912 216.86743,79.324953 216.86743,70.570535 C 216.86743,61.178248 216.3846,54.16153 215.41887,49.520339 L 222.69791,48.695493 M 224.2551,39.490159 C 224.2551,40.611994 223.85673,41.590815 223.06006,42.42662 C 222.26332,43.240515 221.14069,43.647442 219.69213,43.647399 C 218.46084,43.647442 217.49515,43.295504 216.795,42.591595 C 216.119,41.865769 215.781,40.996927 215.781,39.98507 C 215.781,38.885304 216.19144,37.928485 217.01231,37.114591 C 217.83316,36.30078 218.96785,35.893853 220.4164,35.893811 C 221.5994,35.893853 222.52889,36.256783 223.20492,36.982609 C 223.90503,37.686526 224.2551,38.522373 224.2551,39.490159 M 259.60008,80.732697 L 253.91446,80.930661 C 253.62473,79.852857 253.47987,78.830045 253.4799,77.862216 L 253.11774,77.862216 C 250.14817,80.325772 246.10427,81.557546 240.98606,81.557547 C 238.20962,81.557546 235.8195,80.820682 233.81563,79.346948 C 231.81178,77.851221 230.80988,75.728607 230.80988,72.979099 C 230.80988,69.591724 232.37914,66.875216 235.51769,64.829574 C 238.65625,62.761967 244.48667,61.67316 253.00913,61.563165 C 253.08155,61.035275 253.11772,60.430386 253.11774,59.748497 C 253.11772,57.043003 252.32104,55.239336 250.72765,54.337474 C 249.15832,53.435661 246.76819,52.984747 243.55721,52.984714 C 239.76681,52.984747 236.03678,53.413668 232.3671,54.271484 L 232.9827,49.718301 C 236.60411,48.77251 240.76873,48.299592 245.47658,48.299567 C 249.77395,48.299592 253.09359,49.113454 255.43545,50.741118 C 257.77728,52.346863 258.94819,55.096363 258.94824,58.989625 C 258.94819,60.023469 258.88785,61.904117 258.76715,64.631608 C 258.67054,67.337133 258.62228,69.140806 258.6223,70.042632 C 258.62228,74.045913 258.94819,77.609265 259.60008,80.732697 M 253.19019,74.331856 C 253.06945,70.988469 253.00909,67.986016 253.00913,65.324484 C 248.47027,65.324498 245.01786,65.632443 242.65187,66.248318 C 238.69248,67.348131 236.71278,69.448748 236.71278,72.550177 C 236.71278,75.541643 239.03044,77.037371 243.66588,77.037366 C 247.64942,77.037371 250.82416,76.135534 253.19019,74.331856"
+ id="text3736"
+ sodipodi:nodetypes="ccsscssccscccsccccsccsccsscsssccccscscccsccccscsssccscscccscccsscsssccccccscsccscsccscscsccccssc" />
+ <path
+ style="fill:url(#radialGradient6564);fill-opacity:1.0;fill-rule:evenodd;stroke:#323232;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 105.45673,18.675923 C 105.45673,18.675923 88.211949,26.918461 74.172834,28.737898 C 60.133727,30.557333 33.360434,32.377571 28.045622,31.093256 C 22.730818,29.808941 18.915645,28.309196 18.915645,28.309196 L 20.021441,32.056583 L 16.609513,35.052471 L 17.2144,36.121726 L 18.61792,36.22764 L 22.92773,36.762252 L 23.532621,38.688909 L 25.937975,38.905784 L 27.143021,42.970927 C 27.143021,42.970927 32.254764,43.399628 33.758953,43.399628 C 35.263142,43.399628 38.271966,43.187802 38.271966,43.187802 L 38.371202,44.791657 L 39.477002,45.003495 L 39.477002,46.824227 L 37.066917,48.967759 L 37.671807,49.073671 L 37.671807,49.820127 C 37.671807,49.820127 32.255457,50.252157 30.049301,49.93109 C 27.843157,49.610006 27.440747,49.608286 27.440747,49.608286 L 27.242258,49.820127 L 27.143021,50.783455 L 27.643946,50.783455 L 27.84242,54.959544 L 38.976091,54.530844 L 38.172728,68.980747 L 38.073481,70.796442 L 28.645781,70.261816 L 28.546544,66.408513 L 30.649462,66.408513 L 30.852673,64.910557 L 32.757107,64.481857 L 33.059555,64.058192 L 25.937975,62.343374 L 20.522364,63.947229 L 21.42496,64.698732 L 22.327572,64.698732 L 22.426809,65.984848 L 24.331254,66.09076 L 24.331254,69.838147 L 22.228335,70.372777 L 22.630009,71.225146 L 23.130934,71.547931 L 23.130934,74.437917 L 24.435218,74.437917 L 24.435218,87.813529 L 22.327572,88.13632 L 22.630009,91.989617 L 23.929569,92.206492 L 23.731093,100.98236 L 29.449141,101.08826 L 28.244105,92.418334 L 36.868446,92.206492 L 36.268285,96.912181 L 35.464925,100.23086 L 44.188501,100.33677 L 44.287739,91.777793 L 50.303506,91.243181 L 50.005786,96.700351 L 49.802585,99.90807 L 54.920484,99.90807 L 54.717274,91.132217 L 55.421397,91.243181 L 55.619882,87.067076 L 54.816521,87.067076 L 54.518798,85.352258 L 54.017874,80.429702 L 54.216359,74.760706 L 55.31743,74.760706 L 55.31743,71.336105 L 53.913913,71.442015 L 54.117112,67.402096 L 55.747469,67.240708 L 55.823083,65.929374 L 56.749319,65.793192 L 57.699176,65.071956 L 51.985842,63.896802 L 46.31977,65.15265 L 46.872668,66.060507 L 47.47283,66.010066 L 48.172228,65.984848 L 48.299828,67.639144 L 49.878196,67.563497 L 49.906548,71.144447 L 43.111042,70.988097 L 43.337879,67.160002 L 43.559978,63.679927 L 43.559978,59.105378 L 43.763188,54.288748 L 57.373101,53.592733 L 73.567955,52.659674 L 73.71917,55.736265 L 73.142647,63.120082 L 72.892183,69.9945 L 66.928387,69.888585 L 66.900039,65.071956 L 69.106918,64.991267 L 69.206169,63.629486 L 70.108765,63.493308 L 70.061506,63.226006 L 70.964116,63.175568 L 71.465028,62.504773 L 64.721507,60.926122 L 58.001612,62.368592 L 58.4789,63.200785 L 59.230285,63.1453 L 59.230285,63.523577 L 60.156518,63.523577 L 60.156518,65.046738 L 62.136575,65.071956 L 62.112937,69.298485 L 60.109259,69.298485 L 60.080907,70.261816 L 60.785031,70.342507 L 60.70942,74.009202 L 62.188552,74.089909 L 62.013701,88.620507 L 60.057282,89.018952 L 60.080907,89.714967 L 60.761406,89.714967 L 60.761406,93.437137 L 61.886113,93.437137 L 61.588391,98.52109 L 61.210343,102.95945 L 68.331912,103.14605 L 68.105084,99.29275 L 67.580538,96.085028 L 67.476575,93.300955 L 73.520696,93.195041 L 73.345845,97.502272 L 73.317494,102.05159 L 76.729426,102.3189 L 81.3653,102.1323 L 82.820807,101.70358 L 82.017437,99.26753 L 81.818959,95.439438 L 81.440912,92.710853 L 87.206218,92.499027 L 86.955759,95.842931 L 86.932133,101.08826 L 89.238253,101.30009 L 91.520751,101.24965 L 92.621828,100.90165 L 91.969693,95.923633 L 91.747577,92.176239 L 92.725793,92.070324 L 92.749427,88.726422 L 93.02352,88.670945 L 92.976244,87.949712 L 91.846823,87.949712 L 91.619996,85.488427 L 91.520751,74.811143 L 92.371377,74.785924 L 92.371377,71.280616 L 92.725793,71.336105 L 92.725793,70.640088 L 91.468773,70.529127 L 91.497126,66.463987 L 93.600043,66.277382 L 93.477182,64.910557 L 94.403419,64.829863 L 94.351424,64.562549 L 95.580099,63.947229 L 89.337489,62.69138 L 82.995657,63.977495 L 83.39733,64.723951 L 84.375543,64.643256 L 84.427528,64.966046 L 85.254515,64.966046 L 85.301775,66.569901 L 87.357445,66.544681 L 87.532293,70.478688 L 80.264217,70.423216 L 79.413593,64.512124 L 78.733106,61.380041 L 78.184923,55.761484 L 78.510996,52.473053 L 92.999878,51.373557 L 93.047136,46.476221 L 93.774891,46.289613 L 93.727651,45.543159 L 93.174743,45.220372 C 93.174629,45.220372 85.252181,46.395266 82.745197,46.66284 C 82.0389,46.738209 82.09239,46.733258 81.516524,46.79397 L 81.440912,45.886118 L 78.444837,44.317564 L 78.482644,42.491786 L 79.512842,42.461518 L 79.588444,39.949808 C 79.588444,39.949808 85.728225,39.546834 88.009582,39.0117 C 90.290937,38.476559 93.524432,37.942456 93.524432,37.942456 L 95.055545,33.79662 L 98.089437,32.913987 L 98.339888,32.217972 L 105.20628,30.316548 L 105.98602,29.676006 L 103.37744,23.976741 L 103.62792,22.690624 L 104.95584,21.994611 L 105.91041,19.079404 L 105.45673,18.675923 z M 72.466874,40.403728 L 72.429067,42.476654 L 73.983813,42.542211 L 73.884576,44.509221 L 70.836515,46.506487 L 70.647496,47.081457 L 71.876167,47.091543 L 71.866712,47.575729 L 62.552432,48.029652 L 62.613863,46.652742 L 63.039175,45.966809 L 63.067524,45.528025 L 63.07698,44.579832 L 63.341609,43.949374 L 63.440849,43.439982 L 63.440849,43.076841 L 63.842533,41.47297 L 72.466874,40.403728 z M 52.987688,42.168984 L 52.760853,43.561027 L 53.488599,44.418431 L 53.441349,45.916386 L 54.117112,46.960408 L 53.942262,48.191039 L 54.443185,48.912273 L 44.939872,49.2855 L 44.916247,48.967759 L 46.017333,48.831579 L 46.069307,48.428097 L 43.66394,47.121797 L 43.536351,45.03375 L 44.689411,44.978276 L 44.788661,42.72883 L 52.987688,42.168984 z M 67.051262,74.276518 L 72.81657,74.649742 L 72.618099,82.411833 L 73.36947,88.776857 L 67.254465,88.565018 L 67.051262,74.276518 z M 28.44258,74.599304 L 37.671807,75.078442 L 36.868446,80.429702 L 36.868446,84.928593 L 37.520583,87.440302 L 28.494569,87.869006 L 28.44258,74.599304 z M 87.508658,74.649742 L 87.508658,87.924488 L 81.644113,88.353194 L 81.440912,81.342592 L 80.788764,74.811143 L 87.508658,74.649742 z M 43.087416,74.947312 L 49.906548,74.972531 L 49.977434,87.278902 L 43.611966,87.389863 L 43.285891,83.400379 L 43.262266,79.441156 L 43.087416,74.947312 z "
+ id="path4735" />
+ </g>
+</svg>
diff --git a/deps/v8_inspector/deps/jinja2/docs/Makefile b/deps/v8_inspector/deps/jinja2/docs/Makefile
new file mode 100644
index 0000000000..52d78d9efe
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/Makefile
@@ -0,0 +1,118 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp epub latex changes linkcheck doctest
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+ -rm -rf $(BUILDDIR)/*
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Flask.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Flask.qhc"
+
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) _build/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/Flask"
+ @echo "# ln -s _build/devhelp $$HOME/.local/share/devhelp/Flask"
+ @echo "# devhelp"
+
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
+ "run these through (pdf)latex."
+
+latexpdf: latex
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex
+ @echo "Running LaTeX files through pdflatex..."
+ make -C _build/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in _build/latex."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
diff --git a/deps/v8_inspector/deps/jinja2/docs/_static/.ignore b/deps/v8_inspector/deps/jinja2/docs/_static/.ignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/_static/.ignore
diff --git a/deps/v8_inspector/deps/jinja2/docs/_static/jinja-small.png b/deps/v8_inspector/deps/jinja2/docs/_static/jinja-small.png
new file mode 100644
index 0000000000..455b4c3c99
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/_static/jinja-small.png
Binary files differ
diff --git a/deps/v8_inspector/deps/jinja2/docs/_templates/sidebarintro.html b/deps/v8_inspector/deps/jinja2/docs/_templates/sidebarintro.html
new file mode 100644
index 0000000000..b7fcfda412
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/_templates/sidebarintro.html
@@ -0,0 +1,20 @@
+<h3>About Jinja2</h3>
+<p>
+ Jinja2 is a full featured template engine for Python. It has full unicode
+ support, an optional integrated sandboxed execution environment, widely used
+ and BSD licensed.
+</p>
+<h3>Other Formats</h3>
+<p>
+ You can download the documentation in other formats as well:
+</p>
+<ul>
+ <li><a href="http://jinja.pocoo.org/docs/jinja-docs.pdf">as PDF</a>
+ <li><a href="http://jinja.pocoo.org/docs/jinja-docs.zip">as zipped HTML</a>
+</ul>
+<h3>Useful Links</h3>
+<ul>
+ <li><a href="http://jinja.pocoo.org/">The Jinja2 Website</a></li>
+ <li><a href="http://pypi.python.org/pypi/Jinja2">Jinja2 @ PyPI</a></li>
+ <li><a href="http://github.com/mitsuhiko/jinja2">Jinja2 @ github</a></li>
+</ul>
diff --git a/deps/v8_inspector/deps/jinja2/docs/_templates/sidebarlogo.html b/deps/v8_inspector/deps/jinja2/docs/_templates/sidebarlogo.html
new file mode 100644
index 0000000000..ca211c6a3e
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/_templates/sidebarlogo.html
@@ -0,0 +1,3 @@
+<p class="logo"><a href="{{ pathto(master_doc) }}">
+ <img class="logo" src="{{ pathto('_static/jinja-small.png', 1) }}" alt="Logo"/>
+</a></p>
diff --git a/deps/v8_inspector/deps/jinja2/docs/_themes/LICENSE b/deps/v8_inspector/deps/jinja2/docs/_themes/LICENSE
new file mode 100644
index 0000000000..8daab7ee6e
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/_themes/LICENSE
@@ -0,0 +1,37 @@
+Copyright (c) 2010 by Armin Ronacher.
+
+Some rights reserved.
+
+Redistribution and use in source and binary forms of the theme, with or
+without modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+* The names of the contributors may not be used to endorse or
+ promote products derived from this software without specific
+ prior written permission.
+
+We kindly ask you to only use these themes in an unmodified manner just
+for Flask and Flask-related products, not for unrelated projects. If you
+like the visual style and want to use it for your own projects, please
+consider making some larger changes to the themes (such as changing
+font faces, sizes, colors or margins).
+
+THIS THEME IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS THEME, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/deps/v8_inspector/deps/jinja2/docs/_themes/README b/deps/v8_inspector/deps/jinja2/docs/_themes/README
new file mode 100644
index 0000000000..b3292bdff8
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/_themes/README
@@ -0,0 +1,31 @@
+Flask Sphinx Styles
+===================
+
+This repository contains sphinx styles for Flask and Flask related
+projects. To use this style in your Sphinx documentation, follow
+this guide:
+
+1. put this folder as _themes into your docs folder. Alternatively
+ you can also use git submodules to check out the contents there.
+2. add this to your conf.py:
+
+ sys.path.append(os.path.abspath('_themes'))
+ html_theme_path = ['_themes']
+ html_theme = 'flask'
+
+The following themes exist:
+
+- 'flask' - the standard flask documentation theme for large
+ projects
+- 'flask_small' - small one-page theme. Intended to be used by
+ very small addon libraries for flask.
+
+The following options exist for the flask_small theme:
+
+ [options]
+ index_logo = '' filename of a picture in _static
+ to be used as replacement for the
+ h1 in the index.rst file.
+ index_logo_height = 120px height of the index logo
+ github_fork = '' repository name on github for the
+ "fork me" badge
diff --git a/deps/v8_inspector/deps/jinja2/docs/_themes/jinja/layout.html b/deps/v8_inspector/deps/jinja2/docs/_themes/jinja/layout.html
new file mode 100644
index 0000000000..a0c9cab042
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/_themes/jinja/layout.html
@@ -0,0 +1,8 @@
+{%- extends "basic/layout.html" %}
+{%- block relbar2 %}{% endblock %}
+{%- block footer %}
+ <div class="footer">
+ &copy; Copyright {{ copyright }}.
+ Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.
+ </div>
+{%- endblock %}
diff --git a/deps/v8_inspector/deps/jinja2/docs/_themes/jinja/relations.html b/deps/v8_inspector/deps/jinja2/docs/_themes/jinja/relations.html
new file mode 100644
index 0000000000..3bbcde85bb
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/_themes/jinja/relations.html
@@ -0,0 +1,19 @@
+<h3>Related Topics</h3>
+<ul>
+ <li><a href="{{ pathto(master_doc) }}">Documentation overview</a><ul>
+ {%- for parent in parents %}
+ <li><a href="{{ parent.link|e }}">{{ parent.title }}</a><ul>
+ {%- endfor %}
+ {%- if prev %}
+ <li>Previous: <a href="{{ prev.link|e }}" title="{{ _('previous chapter')
+ }}">{{ prev.title }}</a></li>
+ {%- endif %}
+ {%- if next %}
+ <li>Next: <a href="{{ next.link|e }}" title="{{ _('next chapter')
+ }}">{{ next.title }}</a></li>
+ {%- endif %}
+ {%- for parent in parents %}
+ </ul></li>
+ {%- endfor %}
+ </ul></li>
+</ul>
diff --git a/deps/v8_inspector/deps/jinja2/docs/_themes/jinja/static/jinja.css_t b/deps/v8_inspector/deps/jinja2/docs/_themes/jinja/static/jinja.css_t
new file mode 100644
index 0000000000..7d3b244ae1
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/_themes/jinja/static/jinja.css_t
@@ -0,0 +1,396 @@
+/*
+ * jinja.css_t
+ * ~~~~~~~~~~~
+ *
+ * :copyright: Copyright 2011 by Armin Ronacher.
+ * :license: Flask Design License, see LICENSE for details.
+ */
+
+@import url(http://fonts.googleapis.com/css?family=Crimson+Text);
+
+{% set page_width = '940px' %}
+{% set sidebar_width = '220px' %}
+{% set font_family = 'Georgia, serif' %}
+{% set header_font_family = 'Crimson Text, ' ~ font_family %}
+
+@import url("basic.css");
+
+/* -- page layout ----------------------------------------------------------- */
+
+body {
+ font-family: {{ font_family }};
+ font-size: 17px;
+ background-color: white;
+ color: #000;
+ margin: 0;
+ padding: 0;
+}
+
+div.document {
+ width: {{ page_width }};
+ margin: 30px auto 0 auto;
+}
+
+div.documentwrapper {
+ float: left;
+ width: 100%;
+}
+
+div.bodywrapper {
+ margin: 0 0 0 {{ sidebar_width }};
+}
+
+div.sphinxsidebar {
+ width: {{ sidebar_width }};
+}
+
+hr {
+ border: 1px solid #B1B4B6;
+}
+
+div.body {
+ background-color: #ffffff;
+ color: #3E4349;
+ padding: 0 30px 0 30px;
+}
+
+img.floatingflask {
+ padding: 0 0 10px 10px;
+ float: right;
+}
+
+div.footer {
+ width: {{ page_width }};
+ margin: 20px auto 30px auto;
+ font-size: 14px;
+ color: #888;
+ text-align: right;
+}
+
+div.footer a {
+ color: #888;
+}
+
+div.related {
+ display: none;
+}
+
+div.sphinxsidebar a {
+ color: #444;
+ text-decoration: none;
+ border-bottom: 1px dotted #999;
+}
+
+div.sphinxsidebar a:hover {
+ border-bottom: 1px solid #999;
+}
+
+div.sphinxsidebar {
+ font-size: 15px;
+ line-height: 1.5;
+}
+
+div.sphinxsidebarwrapper {
+ padding: 18px 10px;
+}
+
+div.sphinxsidebarwrapper p.logo {
+ padding: 0 0 20px 0;
+ margin: 0;
+ text-align: center;
+}
+
+div.sphinxsidebar h3,
+div.sphinxsidebar h4 {
+ font-family: {{ font_family }};
+ color: #444;
+ font-size: 24px;
+ font-weight: normal;
+ margin: 0 0 5px 0;
+ padding: 0;
+}
+
+div.sphinxsidebar h4 {
+ font-size: 20px;
+}
+
+div.sphinxsidebar h3 a {
+ color: #444;
+}
+
+div.sphinxsidebar p.logo a,
+div.sphinxsidebar h3 a,
+div.sphinxsidebar p.logo a:hover,
+div.sphinxsidebar h3 a:hover {
+ border: none;
+}
+
+div.sphinxsidebar p {
+ color: #555;
+ margin: 10px 0;
+}
+
+div.sphinxsidebar ul {
+ margin: 10px 0;
+ padding: 0;
+ color: #000;
+}
+
+div.sphinxsidebar input {
+ border: 1px solid #ccc;
+ font-family: {{ font_family }};
+ font-size: 14px;
+}
+
+div.sphinxsidebar form.search input[name="q"] {
+ width: 130px;
+}
+
+/* -- body styles ----------------------------------------------------------- */
+
+a {
+ color: #aa0000;
+ text-decoration: underline;
+}
+
+a:hover {
+ color: #dd0000;
+ text-decoration: underline;
+}
+
+div.body h1,
+div.body h2,
+div.body h3,
+div.body h4,
+div.body h5,
+div.body h6 {
+ font-family: {{ header_font_family }};
+ font-weight: normal;
+ margin: 30px 0px 10px 0px;
+ padding: 0;
+ color: black;
+}
+
+div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; }
+div.body h2 { font-size: 180%; }
+div.body h3 { font-size: 150%; }
+div.body h4 { font-size: 130%; }
+div.body h5 { font-size: 100%; }
+div.body h6 { font-size: 100%; }
+
+a.headerlink {
+ color: #ddd;
+ padding: 0 4px;
+ text-decoration: none;
+}
+
+a.headerlink:hover {
+ color: #444;
+ background: #eaeaea;
+}
+
+div.body p, div.body dd, div.body li {
+ line-height: 1.4em;
+}
+
+div.admonition {
+ background: #fafafa;
+ margin: 20px -30px;
+ padding: 10px 30px;
+ border-top: 1px solid #ccc;
+ border-bottom: 1px solid #ccc;
+}
+
+div.admonition tt.xref, div.admonition a tt {
+ border-bottom: 1px solid #fafafa;
+}
+
+dd div.admonition {
+ margin-left: -60px;
+ padding-left: 60px;
+}
+
+div.admonition p.admonition-title {
+ font-family: {{ font_family }};
+ font-weight: normal;
+ font-size: 24px;
+ margin: 0 0 10px 0;
+ padding: 0;
+ line-height: 1;
+}
+
+div.admonition p.last {
+ margin-bottom: 0;
+}
+
+div.highlight {
+ background-color: white;
+}
+
+dt:target, .highlight {
+ background: #FAF3E8;
+}
+
+div.note {
+ background-color: #eee;
+ border: 1px solid #ccc;
+}
+
+div.seealso {
+ background-color: #ffc;
+ border: 1px solid #ff6;
+}
+
+div.topic {
+ background-color: #eee;
+}
+
+p.admonition-title {
+ display: inline;
+}
+
+p.admonition-title:after {
+ content: ":";
+}
+
+pre, tt {
+ font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
+ font-size: 0.85em;
+}
+
+img.screenshot {
+}
+
+tt.descname, tt.descclassname {
+ font-size: 0.95em;
+}
+
+tt.descname {
+ padding-right: 0.08em;
+}
+
+img.screenshot {
+ -moz-box-shadow: 2px 2px 4px #eee;
+ -webkit-box-shadow: 2px 2px 4px #eee;
+ box-shadow: 2px 2px 4px #eee;
+}
+
+table.docutils {
+ border: 1px solid #888;
+ -moz-box-shadow: 2px 2px 4px #eee;
+ -webkit-box-shadow: 2px 2px 4px #eee;
+ box-shadow: 2px 2px 4px #eee;
+}
+
+table.docutils td, table.docutils th {
+ border: 1px solid #888;
+ padding: 0.25em 0.7em;
+}
+
+table.field-list, table.footnote {
+ border: none;
+ -moz-box-shadow: none;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+
+table.footnote {
+ margin: 15px 0;
+ width: 100%;
+ border: 1px solid #eee;
+ background: #fdfdfd;
+ font-size: 0.9em;
+}
+
+table.footnote + table.footnote {
+ margin-top: -15px;
+ border-top: none;
+}
+
+table.field-list th {
+ padding: 0 0.8em 0 0;
+}
+
+table.field-list td {
+ padding: 0;
+}
+
+table.footnote td.label {
+ width: 0px;
+ padding: 0.3em 0 0.3em 0.5em;
+}
+
+table.footnote td {
+ padding: 0.3em 0.5em;
+}
+
+dl {
+ margin: 0;
+ padding: 0;
+}
+
+dl dd {
+ margin-left: 30px;
+}
+
+blockquote {
+ margin: 0 0 0 30px;
+ padding: 0;
+}
+
+ul, ol {
+ margin: 10px 0 10px 30px;
+ padding: 0;
+}
+
+pre {
+ background: #eee;
+ padding: 7px 30px;
+ margin: 15px -30px;
+ line-height: 1.3em;
+}
+
+dl pre, blockquote pre, li pre {
+ margin-left: -60px;
+ padding-left: 60px;
+}
+
+dl dl pre {
+ margin-left: -90px;
+ padding-left: 90px;
+}
+
+tt {
+ background-color: #E8EFF0;
+ color: #222;
+ /* padding: 1px 2px; */
+}
+
+tt.xref, a tt {
+ background-color: #E8EFF0;
+ border-bottom: 1px solid white;
+}
+
+a.reference {
+ text-decoration: none;
+ border-bottom: 1px dotted #bb0000;
+}
+
+a.reference:hover {
+ border-bottom: 1px solid #dd0000;
+}
+
+a.footnote-reference {
+ text-decoration: none;
+ font-size: 0.7em;
+ vertical-align: top;
+ border-bottom: 1px dotted #bb0000;
+}
+
+a.footnote-reference:hover {
+ border-bottom: 1px solid #dd0000;
+}
+
+a:hover tt {
+ background: #EEE;
+}
diff --git a/deps/v8_inspector/deps/jinja2/docs/_themes/jinja/theme.conf b/deps/v8_inspector/deps/jinja2/docs/_themes/jinja/theme.conf
new file mode 100644
index 0000000000..10c7e56e83
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/_themes/jinja/theme.conf
@@ -0,0 +1,3 @@
+[theme]
+inherit = basic
+stylesheet = jinja.css
diff --git a/deps/v8_inspector/deps/jinja2/docs/api.rst b/deps/v8_inspector/deps/jinja2/docs/api.rst
new file mode 100644
index 0000000000..04ba157fbb
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/api.rst
@@ -0,0 +1,808 @@
+API
+===
+
+.. module:: jinja2
+ :synopsis: public Jinja2 API
+
+This document describes the API to Jinja2 and not the template language. It
+will be most useful as reference to those implementing the template interface
+to the application and not those who are creating Jinja2 templates.
+
+Basics
+------
+
+Jinja2 uses a central object called the template :class:`Environment`.
+Instances of this class are used to store the configuration and global objects,
+and are used to load templates from the file system or other locations.
+Even if you are creating templates from strings by using the constructor of
+:class:`Template` class, an environment is created automatically for you,
+albeit a shared one.
+
+Most applications will create one :class:`Environment` object on application
+initialization and use that to load templates. In some cases it's however
+useful to have multiple environments side by side, if different configurations
+are in use.
+
+The simplest way to configure Jinja2 to load templates for your application
+looks roughly like this::
+
+ from jinja2 import Environment, PackageLoader
+ env = Environment(loader=PackageLoader('yourapplication', 'templates'))
+
+This will create a template environment with the default settings and a
+loader that looks up the templates in the `templates` folder inside the
+`yourapplication` python package. Different loaders are available
+and you can also write your own if you want to load templates from a
+database or other resources.
+
+To load a template from this environment you just have to call the
+:meth:`get_template` method which then returns the loaded :class:`Template`::
+
+ template = env.get_template('mytemplate.html')
+
+To render it with some variables, just call the :meth:`render` method::
+
+ print template.render(the='variables', go='here')
+
+Using a template loader rather than passing strings to :class:`Template`
+or :meth:`Environment.from_string` has multiple advantages. Besides being
+a lot easier to use it also enables template inheritance.
+
+
+Unicode
+-------
+
+Jinja2 is using Unicode internally which means that you have to pass Unicode
+objects to the render function or bytestrings that only consist of ASCII
+characters. Additionally newlines are normalized to one end of line
+sequence which is per default UNIX style (``\n``).
+
+Python 2.x supports two ways of representing string objects. One is the
+`str` type and the other is the `unicode` type, both of which extend a type
+called `basestring`. Unfortunately the default is `str` which should not
+be used to store text based information unless only ASCII characters are
+used. With Python 2.6 it is possible to make `unicode` the default on a per
+module level and with Python 3 it will be the default.
+
+To explicitly use a Unicode string you have to prefix the string literal
+with a `u`: ``u'Hänsel und Gretel sagen Hallo'``. That way Python will
+store the string as Unicode by decoding the string with the character
+encoding from the current Python module. If no encoding is specified this
+defaults to 'ASCII' which means that you can't use any non ASCII identifier.
+
+To set a better module encoding add the following comment to the first or
+second line of the Python module using the Unicode literal::
+
+ # -*- coding: utf-8 -*-
+
+We recommend utf-8 as Encoding for Python modules and templates as it's
+possible to represent every Unicode character in utf-8 and because it's
+backwards compatible to ASCII. For Jinja2 the default encoding of templates
+is assumed to be utf-8.
+
+It is not possible to use Jinja2 to process non-Unicode data. The reason
+for this is that Jinja2 uses Unicode already on the language level. For
+example Jinja2 treats the non-breaking space as valid whitespace inside
+expressions which requires knowledge of the encoding or operating on an
+Unicode string.
+
+For more details about Unicode in Python have a look at the excellent
+`Unicode documentation`_.
+
+Another important thing is how Jinja2 is handling string literals in
+templates. A naive implementation would be using Unicode strings for
+all string literals but it turned out in the past that this is problematic
+as some libraries are typechecking against `str` explicitly. For example
+`datetime.strftime` does not accept Unicode arguments. To not break it
+completely Jinja2 is returning `str` for strings that fit into ASCII and
+for everything else `unicode`:
+
+>>> m = Template(u"{% set a, b = 'foo', 'föö' %}").module
+>>> m.a
+'foo'
+>>> m.b
+u'f\xf6\xf6'
+
+
+.. _Unicode documentation: http://docs.python.org/dev/howto/unicode.html
+
+High Level API
+--------------
+
+The high-level API is the API you will use in the application to load and
+render Jinja2 templates. The :ref:`low-level-api` on the other side is only
+useful if you want to dig deeper into Jinja2 or :ref:`develop extensions
+<jinja-extensions>`.
+
+.. autoclass:: Environment([options])
+ :members: from_string, get_template, select_template,
+ get_or_select_template, join_path, extend, compile_expression,
+ compile_templates, list_templates, add_extension
+
+ .. attribute:: shared
+
+ If a template was created by using the :class:`Template` constructor
+ an environment is created automatically. These environments are
+ created as shared environments which means that multiple templates
+ may have the same anonymous environment. For all shared environments
+ this attribute is `True`, else `False`.
+
+ .. attribute:: sandboxed
+
+ If the environment is sandboxed this attribute is `True`. For the
+ sandbox mode have a look at the documentation for the
+ :class:`~jinja2.sandbox.SandboxedEnvironment`.
+
+ .. attribute:: filters
+
+ A dict of filters for this environment. As long as no template was
+ loaded it's safe to add new filters or remove old. For custom filters
+ see :ref:`writing-filters`. For valid filter names have a look at
+ :ref:`identifier-naming`.
+
+ .. attribute:: tests
+
+ A dict of test functions for this environment. As long as no
+ template was loaded it's safe to modify this dict. For custom tests
+ see :ref:`writing-tests`. For valid test names have a look at
+ :ref:`identifier-naming`.
+
+ .. attribute:: globals
+
+ A dict of global variables. These variables are always available
+ in a template. As long as no template was loaded it's safe
+ to modify this dict. For more details see :ref:`global-namespace`.
+ For valid object names have a look at :ref:`identifier-naming`.
+
+ .. attribute:: code_generator_class
+
+ The class used for code generation. This should not be changed
+ in most cases, unless you need to modify the Python code a
+ template compiles to.
+
+ .. attribute:: context_class
+
+ The context used for templates. This should not be changed
+ in most cases, unless you need to modify internals of how
+ template variables are handled. For details, see
+ :class:`~jinja2.runtime.Context`.
+
+ .. automethod:: overlay([options])
+
+ .. method:: undefined([hint, obj, name, exc])
+
+ Creates a new :class:`Undefined` object for `name`. This is useful
+ for filters or functions that may return undefined objects for
+ some operations. All parameters except of `hint` should be provided
+ as keyword parameters for better readability. The `hint` is used as
+ error message for the exception if provided, otherwise the error
+ message will be generated from `obj` and `name` automatically. The exception
+ provided as `exc` is raised if something with the generated undefined
+ object is done that the undefined object does not allow. The default
+ exception is :exc:`UndefinedError`. If a `hint` is provided the
+ `name` may be omitted.
+
+ The most common way to create an undefined object is by providing
+ a name only::
+
+ return environment.undefined(name='some_name')
+
+ This means that the name `some_name` is not defined. If the name
+ was from an attribute of an object it makes sense to tell the
+ undefined object the holder object to improve the error message::
+
+ if not hasattr(obj, 'attr'):
+ return environment.undefined(obj=obj, name='attr')
+
+ For a more complex example you can provide a hint. For example
+ the :func:`first` filter creates an undefined object that way::
+
+ return environment.undefined('no first item, sequence was empty')
+
+ If it the `name` or `obj` is known (for example because an attribute
+ was accessed) it should be passed to the undefined object, even if
+ a custom `hint` is provided. This gives undefined objects the
+ possibility to enhance the error message.
+
+.. autoclass:: Template
+ :members: module, make_module
+
+ .. attribute:: globals
+
+ The dict with the globals of that template. It's unsafe to modify
+ this dict as it may be shared with other templates or the environment
+ that loaded the template.
+
+ .. attribute:: name
+
+ The loading name of the template. If the template was loaded from a
+ string this is `None`.
+
+ .. attribute:: filename
+
+ The filename of the template on the file system if it was loaded from
+ there. Otherwise this is `None`.
+
+ .. automethod:: render([context])
+
+ .. automethod:: generate([context])
+
+ .. automethod:: stream([context])
+
+
+.. autoclass:: jinja2.environment.TemplateStream()
+ :members: disable_buffering, enable_buffering, dump
+
+
+Autoescaping
+------------
+
+.. versionadded:: 2.4
+
+As of Jinja 2.4 the preferred way to do autoescaping is to enable the
+:ref:`autoescape-extension` and to configure a sensible default for
+autoescaping. This makes it possible to enable and disable autoescaping
+on a per-template basis (HTML versus text for instance).
+
+Here a recommended setup that enables autoescaping for templates ending
+in ``'.html'``, ``'.htm'`` and ``'.xml'`` and disabling it by default
+for all other extensions::
+
+ def guess_autoescape(template_name):
+ if template_name is None or '.' not in template_name:
+ return False
+ ext = template_name.rsplit('.', 1)[1]
+ return ext in ('html', 'htm', 'xml')
+
+ env = Environment(autoescape=guess_autoescape,
+ loader=PackageLoader('mypackage'),
+ extensions=['jinja2.ext.autoescape'])
+
+When implementing a guessing autoescape function, make sure you also
+accept `None` as valid template name. This will be passed when generating
+templates from strings.
+
+Inside the templates the behaviour can be temporarily changed by using
+the `autoescape` block (see :ref:`autoescape-overrides`).
+
+
+.. _identifier-naming:
+
+Notes on Identifiers
+--------------------
+
+Jinja2 uses the regular Python 2.x naming rules. Valid identifiers have to
+match ``[a-zA-Z_][a-zA-Z0-9_]*``. As a matter of fact non ASCII characters
+are currently not allowed. This limitation will probably go away as soon as
+unicode identifiers are fully specified for Python 3.
+
+Filters and tests are looked up in separate namespaces and have slightly
+modified identifier syntax. Filters and tests may contain dots to group
+filters and tests by topic. For example it's perfectly valid to add a
+function into the filter dict and call it `to.unicode`. The regular
+expression for filter and test identifiers is
+``[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)*```.
+
+
+Undefined Types
+---------------
+
+These classes can be used as undefined types. The :class:`Environment`
+constructor takes an `undefined` parameter that can be one of those classes
+or a custom subclass of :class:`Undefined`. Whenever the template engine is
+unable to look up a name or access an attribute one of those objects is
+created and returned. Some operations on undefined values are then allowed,
+others fail.
+
+The closest to regular Python behavior is the `StrictUndefined` which
+disallows all operations beside testing if it's an undefined object.
+
+.. autoclass:: jinja2.Undefined()
+
+ .. attribute:: _undefined_hint
+
+ Either `None` or an unicode string with the error message for
+ the undefined object.
+
+ .. attribute:: _undefined_obj
+
+ Either `None` or the owner object that caused the undefined object
+ to be created (for example because an attribute does not exist).
+
+ .. attribute:: _undefined_name
+
+ The name for the undefined variable / attribute or just `None`
+ if no such information exists.
+
+ .. attribute:: _undefined_exception
+
+ The exception that the undefined object wants to raise. This
+ is usually one of :exc:`UndefinedError` or :exc:`SecurityError`.
+
+ .. method:: _fail_with_undefined_error(\*args, \**kwargs)
+
+ When called with any arguments this method raises
+ :attr:`_undefined_exception` with an error message generated
+ from the undefined hints stored on the undefined object.
+
+.. autoclass:: jinja2.DebugUndefined()
+
+.. autoclass:: jinja2.StrictUndefined()
+
+There is also a factory function that can decorate undefined objects to
+implement logging on failures:
+
+.. autofunction:: jinja2.make_logging_undefined
+
+Undefined objects are created by calling :attr:`undefined`.
+
+.. admonition:: Implementation
+
+ :class:`Undefined` objects are implemented by overriding the special
+ `__underscore__` methods. For example the default :class:`Undefined`
+ class implements `__unicode__` in a way that it returns an empty
+ string, however `__int__` and others still fail with an exception. To
+ allow conversion to int by returning ``0`` you can implement your own::
+
+ class NullUndefined(Undefined):
+ def __int__(self):
+ return 0
+ def __float__(self):
+ return 0.0
+
+ To disallow a method, just override it and raise
+ :attr:`~Undefined._undefined_exception`. Because this is a very common
+ idom in undefined objects there is the helper method
+ :meth:`~Undefined._fail_with_undefined_error` that does the error raising
+ automatically. Here a class that works like the regular :class:`Undefined`
+ but chokes on iteration::
+
+ class NonIterableUndefined(Undefined):
+ __iter__ = Undefined._fail_with_undefined_error
+
+
+The Context
+-----------
+
+.. autoclass:: jinja2.runtime.Context()
+ :members: resolve, get_exported, get_all
+
+ .. attribute:: parent
+
+ A dict of read only, global variables the template looks up. These
+ can either come from another :class:`Context`, from the
+ :attr:`Environment.globals` or :attr:`Template.globals` or points
+ to a dict created by combining the globals with the variables
+ passed to the render function. It must not be altered.
+
+ .. attribute:: vars
+
+ The template local variables. This list contains environment and
+ context functions from the :attr:`parent` scope as well as local
+ modifications and exported variables from the template. The template
+ will modify this dict during template evaluation but filters and
+ context functions are not allowed to modify it.
+
+ .. attribute:: environment
+
+ The environment that loaded the template.
+
+ .. attribute:: exported_vars
+
+ This set contains all the names the template exports. The values for
+ the names are in the :attr:`vars` dict. In order to get a copy of the
+ exported variables as dict, :meth:`get_exported` can be used.
+
+ .. attribute:: name
+
+ The load name of the template owning this context.
+
+ .. attribute:: blocks
+
+ A dict with the current mapping of blocks in the template. The keys
+ in this dict are the names of the blocks, and the values a list of
+ blocks registered. The last item in each list is the current active
+ block (latest in the inheritance chain).
+
+ .. attribute:: eval_ctx
+
+ The current :ref:`eval-context`.
+
+ .. automethod:: jinja2.runtime.Context.call(callable, \*args, \**kwargs)
+
+
+.. admonition:: Implementation
+
+ Context is immutable for the same reason Python's frame locals are
+ immutable inside functions. Both Jinja2 and Python are not using the
+ context / frame locals as data storage for variables but only as primary
+ data source.
+
+ When a template accesses a variable the template does not define, Jinja2
+ looks up the variable in the context, after that the variable is treated
+ as if it was defined in the template.
+
+
+.. _loaders:
+
+Loaders
+-------
+
+Loaders are responsible for loading templates from a resource such as the
+file system. The environment will keep the compiled modules in memory like
+Python's `sys.modules`. Unlike `sys.modules` however this cache is limited in
+size by default and templates are automatically reloaded.
+All loaders are subclasses of :class:`BaseLoader`. If you want to create your
+own loader, subclass :class:`BaseLoader` and override `get_source`.
+
+.. autoclass:: jinja2.BaseLoader
+ :members: get_source, load
+
+Here a list of the builtin loaders Jinja2 provides:
+
+.. autoclass:: jinja2.FileSystemLoader
+
+.. autoclass:: jinja2.PackageLoader
+
+.. autoclass:: jinja2.DictLoader
+
+.. autoclass:: jinja2.FunctionLoader
+
+.. autoclass:: jinja2.PrefixLoader
+
+.. autoclass:: jinja2.ChoiceLoader
+
+.. autoclass:: jinja2.ModuleLoader
+
+
+.. _bytecode-cache:
+
+Bytecode Cache
+--------------
+
+Jinja 2.1 and higher support external bytecode caching. Bytecode caches make
+it possible to store the generated bytecode on the file system or a different
+location to avoid parsing the templates on first use.
+
+This is especially useful if you have a web application that is initialized on
+the first request and Jinja compiles many templates at once which slows down
+the application.
+
+To use a bytecode cache, instantiate it and pass it to the :class:`Environment`.
+
+.. autoclass:: jinja2.BytecodeCache
+ :members: load_bytecode, dump_bytecode, clear
+
+.. autoclass:: jinja2.bccache.Bucket
+ :members: write_bytecode, load_bytecode, bytecode_from_string,
+ bytecode_to_string, reset
+
+ .. attribute:: environment
+
+ The :class:`Environment` that created the bucket.
+
+ .. attribute:: key
+
+ The unique cache key for this bucket
+
+ .. attribute:: code
+
+ The bytecode if it's loaded, otherwise `None`.
+
+
+Builtin bytecode caches:
+
+.. autoclass:: jinja2.FileSystemBytecodeCache
+
+.. autoclass:: jinja2.MemcachedBytecodeCache
+
+
+Utilities
+---------
+
+These helper functions and classes are useful if you add custom filters or
+functions to a Jinja2 environment.
+
+.. autofunction:: jinja2.environmentfilter
+
+.. autofunction:: jinja2.contextfilter
+
+.. autofunction:: jinja2.evalcontextfilter
+
+.. autofunction:: jinja2.environmentfunction
+
+.. autofunction:: jinja2.contextfunction
+
+.. autofunction:: jinja2.evalcontextfunction
+
+.. function:: escape(s)
+
+ Convert the characters ``&``, ``<``, ``>``, ``'``, and ``"`` in string `s`
+ to HTML-safe sequences. Use this if you need to display text that might
+ contain such characters in HTML. This function will not escaped objects
+ that do have an HTML representation such as already escaped data.
+
+ The return value is a :class:`Markup` string.
+
+.. autofunction:: jinja2.clear_caches
+
+.. autofunction:: jinja2.is_undefined
+
+.. autoclass:: jinja2.Markup([string])
+ :members: escape, unescape, striptags
+
+.. admonition:: Note
+
+ The Jinja2 :class:`Markup` class is compatible with at least Pylons and
+ Genshi. It's expected that more template engines and framework will pick
+ up the `__html__` concept soon.
+
+
+Exceptions
+----------
+
+.. autoexception:: jinja2.TemplateError
+
+.. autoexception:: jinja2.UndefinedError
+
+.. autoexception:: jinja2.TemplateNotFound
+
+.. autoexception:: jinja2.TemplatesNotFound
+
+.. autoexception:: jinja2.TemplateSyntaxError
+
+ .. attribute:: message
+
+ The error message as utf-8 bytestring.
+
+ .. attribute:: lineno
+
+ The line number where the error occurred
+
+ .. attribute:: name
+
+ The load name for the template as unicode string.
+
+ .. attribute:: filename
+
+ The filename that loaded the template as bytestring in the encoding
+ of the file system (most likely utf-8 or mbcs on Windows systems).
+
+ The reason why the filename and error message are bytestrings and not
+ unicode strings is that Python 2.x is not using unicode for exceptions
+ and tracebacks as well as the compiler. This will change with Python 3.
+
+.. autoexception:: jinja2.TemplateAssertionError
+
+
+.. _writing-filters:
+
+Custom Filters
+--------------
+
+Custom filters are just regular Python functions that take the left side of
+the filter as first argument and the the arguments passed to the filter as
+extra arguments or keyword arguments.
+
+For example in the filter ``{{ 42|myfilter(23) }}`` the function would be
+called with ``myfilter(42, 23)``. Here for example a simple filter that can
+be applied to datetime objects to format them::
+
+ def datetimeformat(value, format='%H:%M / %d-%m-%Y'):
+ return value.strftime(format)
+
+You can register it on the template environment by updating the
+:attr:`~Environment.filters` dict on the environment::
+
+ environment.filters['datetimeformat'] = datetimeformat
+
+Inside the template it can then be used as follows:
+
+.. sourcecode:: jinja
+
+ written on: {{ article.pub_date|datetimeformat }}
+ publication date: {{ article.pub_date|datetimeformat('%d-%m-%Y') }}
+
+Filters can also be passed the current template context or environment. This
+is useful if a filter wants to return an undefined value or check the current
+:attr:`~Environment.autoescape` setting. For this purpose three decorators
+exist: :func:`environmentfilter`, :func:`contextfilter` and
+:func:`evalcontextfilter`.
+
+Here a small example filter that breaks a text into HTML line breaks and
+paragraphs and marks the return value as safe HTML string if autoescaping is
+enabled::
+
+ import re
+ from jinja2 import evalcontextfilter, Markup, escape
+
+ _paragraph_re = re.compile(r'(?:\r\n|\r|\n){2,}')
+
+ @evalcontextfilter
+ def nl2br(eval_ctx, value):
+ result = u'\n\n'.join(u'<p>%s</p>' % p.replace('\n', Markup('<br>\n'))
+ for p in _paragraph_re.split(escape(value)))
+ if eval_ctx.autoescape:
+ result = Markup(result)
+ return result
+
+Context filters work the same just that the first argument is the current
+active :class:`Context` rather then the environment.
+
+
+.. _eval-context:
+
+Evaluation Context
+------------------
+
+The evaluation context (short eval context or eval ctx) is a new object
+introduced in Jinja 2.4 that makes it possible to activate and deactivate
+compiled features at runtime.
+
+Currently it is only used to enable and disable the automatic escaping but
+can be used for extensions as well.
+
+In previous Jinja versions filters and functions were marked as
+environment callables in order to check for the autoescape status from the
+environment. In new versions it's encouraged to check the setting from the
+evaluation context instead.
+
+Previous versions::
+
+ @environmentfilter
+ def filter(env, value):
+ result = do_something(value)
+ if env.autoescape:
+ result = Markup(result)
+ return result
+
+In new versions you can either use a :func:`contextfilter` and access the
+evaluation context from the actual context, or use a
+:func:`evalcontextfilter` which directly passes the evaluation context to
+the function::
+
+ @contextfilter
+ def filter(context, value):
+ result = do_something(value)
+ if context.eval_ctx.autoescape:
+ result = Markup(result)
+ return result
+
+ @evalcontextfilter
+ def filter(eval_ctx, value):
+ result = do_something(value)
+ if eval_ctx.autoescape:
+ result = Markup(result)
+ return result
+
+The evaluation context must not be modified at runtime. Modifications
+must only happen with a :class:`nodes.EvalContextModifier` and
+:class:`nodes.ScopedEvalContextModifier` from an extension, not on the
+eval context object itself.
+
+.. autoclass:: jinja2.nodes.EvalContext
+
+ .. attribute:: autoescape
+
+ `True` or `False` depending on if autoescaping is active or not.
+
+ .. attribute:: volatile
+
+ `True` if the compiler cannot evaluate some expressions at compile
+ time. At runtime this should always be `False`.
+
+
+.. _writing-tests:
+
+Custom Tests
+------------
+
+Tests work like filters just that there is no way for a test to get access
+to the environment or context and that they can't be chained. The return
+value of a test should be `True` or `False`. The purpose of a test is to
+give the template designers the possibility to perform type and conformability
+checks.
+
+Here a simple test that checks if a variable is a prime number::
+
+ import math
+
+ def is_prime(n):
+ if n == 2:
+ return True
+ for i in xrange(2, int(math.ceil(math.sqrt(n))) + 1):
+ if n % i == 0:
+ return False
+ return True
+
+
+You can register it on the template environment by updating the
+:attr:`~Environment.tests` dict on the environment::
+
+ environment.tests['prime'] = is_prime
+
+A template designer can then use the test like this:
+
+.. sourcecode:: jinja
+
+ {% if 42 is prime %}
+ 42 is a prime number
+ {% else %}
+ 42 is not a prime number
+ {% endif %}
+
+
+.. _global-namespace:
+
+The Global Namespace
+--------------------
+
+Variables stored in the :attr:`Environment.globals` dict are special as they
+are available for imported templates too, even if they are imported without
+context. This is the place where you can put variables and functions
+that should be available all the time. Additionally :attr:`Template.globals`
+exist that are variables available to a specific template that are available
+to all :meth:`~Template.render` calls.
+
+
+.. _low-level-api:
+
+Low Level API
+-------------
+
+The low level API exposes functionality that can be useful to understand some
+implementation details, debugging purposes or advanced :ref:`extension
+<jinja-extensions>` techniques. Unless you know exactly what you are doing we
+don't recommend using any of those.
+
+.. automethod:: Environment.lex
+
+.. automethod:: Environment.parse
+
+.. automethod:: Environment.preprocess
+
+.. automethod:: Template.new_context
+
+.. method:: Template.root_render_func(context)
+
+ This is the low level render function. It's passed a :class:`Context`
+ that has to be created by :meth:`new_context` of the same template or
+ a compatible template. This render function is generated by the
+ compiler from the template code and returns a generator that yields
+ unicode strings.
+
+ If an exception in the template code happens the template engine will
+ not rewrite the exception but pass through the original one. As a
+ matter of fact this function should only be called from within a
+ :meth:`render` / :meth:`generate` / :meth:`stream` call.
+
+.. attribute:: Template.blocks
+
+ A dict of block render functions. Each of these functions works exactly
+ like the :meth:`root_render_func` with the same limitations.
+
+.. attribute:: Template.is_up_to_date
+
+ This attribute is `False` if there is a newer version of the template
+ available, otherwise `True`.
+
+.. admonition:: Note
+
+ The low-level API is fragile. Future Jinja2 versions will try not to
+ change it in a backwards incompatible way but modifications in the Jinja2
+ core may shine through. For example if Jinja2 introduces a new AST node
+ in later versions that may be returned by :meth:`~Environment.parse`.
+
+The Meta API
+------------
+
+.. versionadded:: 2.2
+
+The meta API returns some information about abstract syntax trees that
+could help applications to implement more advanced template concepts. All
+the functions of the meta API operate on an abstract syntax tree as
+returned by the :meth:`Environment.parse` method.
+
+.. autofunction:: jinja2.meta.find_undeclared_variables
+
+.. autofunction:: jinja2.meta.find_referenced_templates
diff --git a/deps/v8_inspector/deps/jinja2/docs/cache_extension.py b/deps/v8_inspector/deps/jinja2/docs/cache_extension.py
new file mode 100644
index 0000000000..ccdefa2ff3
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/cache_extension.py
@@ -0,0 +1,56 @@
+from jinja2 import nodes
+from jinja2.ext import Extension
+
+
+class FragmentCacheExtension(Extension):
+ # a set of names that trigger the extension.
+ tags = set(['cache'])
+
+ def __init__(self, environment):
+ super(FragmentCacheExtension, self).__init__(environment)
+
+ # add the defaults to the environment
+ environment.extend(
+ fragment_cache_prefix='',
+ fragment_cache=None
+ )
+
+ def parse(self, parser):
+ # the first token is the token that started the tag. In our case
+ # we only listen to ``'cache'`` so this will be a name token with
+ # `cache` as value. We get the line number so that we can give
+ # that line number to the nodes we create by hand.
+ lineno = next(parser.stream).lineno
+
+ # now we parse a single expression that is used as cache key.
+ args = [parser.parse_expression()]
+
+ # if there is a comma, the user provided a timeout. If not use
+ # None as second parameter.
+ if parser.stream.skip_if('comma'):
+ args.append(parser.parse_expression())
+ else:
+ args.append(nodes.Const(None))
+
+ # now we parse the body of the cache block up to `endcache` and
+ # drop the needle (which would always be `endcache` in that case)
+ body = parser.parse_statements(['name:endcache'], drop_needle=True)
+
+ # now return a `CallBlock` node that calls our _cache_support
+ # helper method on this extension.
+ return nodes.CallBlock(self.call_method('_cache_support', args),
+ [], [], body).set_lineno(lineno)
+
+ def _cache_support(self, name, timeout, caller):
+ """Helper callback."""
+ key = self.environment.fragment_cache_prefix + name
+
+ # try to load the block from the cache
+ # if there is no fragment in the cache, render it and store
+ # it in the cache.
+ rv = self.environment.fragment_cache.get(key)
+ if rv is not None:
+ return rv
+ rv = caller()
+ self.environment.fragment_cache.add(key, rv, timeout)
+ return rv
diff --git a/deps/v8_inspector/deps/jinja2/docs/changelog.rst b/deps/v8_inspector/deps/jinja2/docs/changelog.rst
new file mode 100644
index 0000000000..9f11484265
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/changelog.rst
@@ -0,0 +1,3 @@
+.. module:: jinja2
+
+.. include:: ../CHANGES
diff --git a/deps/v8_inspector/deps/jinja2/docs/conf.py b/deps/v8_inspector/deps/jinja2/docs/conf.py
new file mode 100644
index 0000000000..6e990be1c7
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/conf.py
@@ -0,0 +1,160 @@
+# -*- coding: utf-8 -*-
+#
+# Jinja2 documentation build configuration file, created by
+# sphinx-quickstart on Sun Apr 27 21:42:41 2008.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# The contents of this file are pickled, so don't put values in the namespace
+# that aren't pickleable (module imports are okay, they're removed automatically).
+#
+# All configuration values have a default value; values that are commented out
+# serve to show the default value.
+
+import sys, os
+
+# If your extensions are in another directory, add it here. If the directory
+# is relative to the documentation root, use os.path.abspath to make it
+# absolute, like shown here.
+sys.path.append(os.path.dirname(os.path.abspath(__file__)))
+
+# General configuration
+# ---------------------
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'jinjaext']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General substitutions.
+project = 'Jinja2'
+copyright = '2008, Armin Ronacher'
+
+# The default replacements for |version| and |release|, also used in various
+# other places throughout the built documents.
+#
+# The short X.Y version.
+import pkg_resources
+try:
+ release = pkg_resources.get_distribution('Jinja2').version
+except ImportError:
+ print 'To build the documentation, The distribution information of Jinja2'
+ print 'Has to be available. Either install the package into your'
+ print 'development environment or run "setup.py develop" to setup the'
+ print 'metadata. A virtualenv is recommended!'
+ sys.exit(1)
+if 'dev' in release:
+ release = release.split('dev')[0] + 'dev'
+version = '.'.join(release.split('.')[:2])
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+#unused_docs = []
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'jinjaext.JinjaStyle'
+
+
+# Options for HTML output
+# -----------------------
+
+html_theme = 'jinja'
+html_theme_path = ['_themes']
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# no modindex
+html_use_modindex = False
+
+# If true, the reST sources are included in the HTML build as _sources/<name>.
+#html_copy_source = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.
+#html_use_opensearch = False
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'Jinja2doc'
+
+
+# Options for LaTeX output
+# ------------------------
+
+# The paper size ('letter' or 'a4').
+latex_paper_size = 'a4'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, document class [howto/manual]).
+latex_documents = [
+ ('latexindex', 'Jinja2.tex', 'Jinja2 Documentation', 'Armin Ronacher',
+ 'manual'),
+]
+
+# Additional stuff for LaTeX
+latex_elements = {
+ 'fontpkg': r'\usepackage{mathpazo}',
+ 'papersize': 'a4paper',
+ 'pointsize': '12pt',
+ 'preamble': r'''
+\usepackage{jinjastyle}
+
+% i hate you latex
+\DeclareUnicodeCharacter{14D}{o}
+'''
+}
+
+latex_use_parts = True
+
+latex_additional_files = ['jinjastyle.sty', 'logo.pdf']
+
+# If false, no module index is generated.
+latex_use_modindex = False
+
+html_sidebars = {
+ 'index': ['sidebarlogo.html', 'sidebarintro.html', 'sourcelink.html',
+ 'searchbox.html'],
+ '**': ['sidebarlogo.html', 'localtoc.html', 'relations.html',
+ 'sourcelink.html', 'searchbox.html']
+}
diff --git a/deps/v8_inspector/deps/jinja2/docs/contents.rst.inc b/deps/v8_inspector/deps/jinja2/docs/contents.rst.inc
new file mode 100644
index 0000000000..7ee68703f4
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/contents.rst.inc
@@ -0,0 +1,23 @@
+Jinja2 Documentation
+--------------------
+
+.. toctree::
+ :maxdepth: 2
+
+ intro
+ api
+ sandbox
+ templates
+ extensions
+ integration
+ switching
+ tricks
+
+Additional Information
+----------------------
+
+.. toctree::
+ :maxdepth: 2
+
+ faq
+ changelog
diff --git a/deps/v8_inspector/deps/jinja2/docs/extensions.rst b/deps/v8_inspector/deps/jinja2/docs/extensions.rst
new file mode 100644
index 0000000000..955708ba4e
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/extensions.rst
@@ -0,0 +1,346 @@
+.. _jinja-extensions:
+
+Extensions
+==========
+
+Jinja2 supports extensions that can add extra filters, tests, globals or even
+extend the parser. The main motivation of extensions is to move often used
+code into a reusable class like adding support for internationalization.
+
+
+Adding Extensions
+-----------------
+
+Extensions are added to the Jinja2 environment at creation time. Once the
+environment is created additional extensions cannot be added. To add an
+extension pass a list of extension classes or import paths to the
+`extensions` parameter of the :class:`Environment` constructor. The following
+example creates a Jinja2 environment with the i18n extension loaded::
+
+ jinja_env = Environment(extensions=['jinja2.ext.i18n'])
+
+
+.. _i18n-extension:
+
+i18n Extension
+--------------
+
+**Import name:** `jinja2.ext.i18n`
+
+The i18n extension can be used in combination with `gettext`_ or `babel`_. If
+the i18n extension is enabled Jinja2 provides a `trans` statement that marks
+the wrapped string as translatable and calls `gettext`.
+
+After enabling, dummy `_` function that forwards calls to `gettext` is added
+to the environment globals. An internationalized application then has to
+provide a `gettext` function and optionally an `ngettext` function into the
+namespace, either globally or for each rendering.
+
+Environment Methods
+~~~~~~~~~~~~~~~~~~~
+
+After enabling the extension, the environment provides the following
+additional methods:
+
+.. method:: jinja2.Environment.install_gettext_translations(translations, newstyle=False)
+
+ Installs a translation globally for that environment. The translations
+ object provided must implement at least `ugettext` and `ungettext`.
+ The `gettext.NullTranslations` and `gettext.GNUTranslations` classes
+ as well as `Babel`_\s `Translations` class are supported.
+
+ .. versionchanged:: 2.5 newstyle gettext added
+
+.. method:: jinja2.Environment.install_null_translations(newstyle=False)
+
+ Install dummy gettext functions. This is useful if you want to prepare
+ the application for internationalization but don't want to implement the
+ full internationalization system yet.
+
+ .. versionchanged:: 2.5 newstyle gettext added
+
+.. method:: jinja2.Environment.install_gettext_callables(gettext, ngettext, newstyle=False)
+
+ Installs the given `gettext` and `ngettext` callables into the
+ environment as globals. They are supposed to behave exactly like the
+ standard library's :func:`gettext.ugettext` and
+ :func:`gettext.ungettext` functions.
+
+ If `newstyle` is activated, the callables are wrapped to work like
+ newstyle callables. See :ref:`newstyle-gettext` for more information.
+
+ .. versionadded:: 2.5
+
+.. method:: jinja2.Environment.uninstall_gettext_translations()
+
+ Uninstall the translations again.
+
+.. method:: jinja2.Environment.extract_translations(source)
+
+ Extract localizable strings from the given template node or source.
+
+ For every string found this function yields a ``(lineno, function,
+ message)`` tuple, where:
+
+ * `lineno` is the number of the line on which the string was found,
+ * `function` is the name of the `gettext` function used (if the
+ string was extracted from embedded Python code), and
+ * `message` is the string itself (a `unicode` object, or a tuple
+ of `unicode` objects for functions with multiple string arguments).
+
+ If `Babel`_ is installed, :ref:`the babel integration <babel-integration>`
+ can be used to extract strings for babel.
+
+For a web application that is available in multiple languages but gives all
+the users the same language (for example a multilingual forum software
+installed for a French community) may load the translations once and add the
+translation methods to the environment at environment generation time::
+
+ translations = get_gettext_translations()
+ env = Environment(extensions=['jinja2.ext.i18n'])
+ env.install_gettext_translations(translations)
+
+The `get_gettext_translations` function would return the translator for the
+current configuration. (For example by using `gettext.find`)
+
+The usage of the `i18n` extension for template designers is covered as part
+:ref:`of the template documentation <i18n-in-templates>`.
+
+.. _gettext: http://docs.python.org/dev/library/gettext
+.. _Babel: http://babel.edgewall.org/
+
+.. _newstyle-gettext:
+
+Newstyle Gettext
+~~~~~~~~~~~~~~~~
+
+.. versionadded:: 2.5
+
+Starting with version 2.5 you can use newstyle gettext calls. These are
+inspired by trac's internal gettext functions and are fully supported by
+the babel extraction tool. They might not work as expected by other
+extraction tools in case you are not using Babel's.
+
+What's the big difference between standard and newstyle gettext calls? In
+general they are less to type and less error prone. Also if they are used
+in an autoescaping environment they better support automatic escaping.
+Here are some common differences between old and new calls:
+
+standard gettext:
+
+.. sourcecode:: html+jinja
+
+ {{ gettext('Hello World!') }}
+ {{ gettext('Hello %(name)s!')|format(name='World') }}
+ {{ ngettext('%(num)d apple', '%(num)d apples', apples|count)|format(
+ num=apples|count
+ )}}
+
+newstyle gettext looks like this instead:
+
+.. sourcecode:: html+jinja
+
+ {{ gettext('Hello World!') }}
+ {{ gettext('Hello %(name)s!', name='World') }}
+ {{ ngettext('%(num)d apple', '%(num)d apples', apples|count) }}
+
+The advantages of newstyle gettext are that you have less to type and that
+named placeholders become mandatory. The latter sounds like a
+disadvantage but solves a lot of troubles translators are often facing
+when they are unable to switch the positions of two placeholder. With
+newstyle gettext, all format strings look the same.
+
+Furthermore with newstyle gettext, string formatting is also used if no
+placeholders are used which makes all strings behave exactly the same.
+Last but not least are newstyle gettext calls able to properly mark
+strings for autoescaping which solves lots of escaping related issues many
+templates are experiencing over time when using autoescaping.
+
+Expression Statement
+--------------------
+
+**Import name:** `jinja2.ext.do`
+
+The "do" aka expression-statement extension adds a simple `do` tag to the
+template engine that works like a variable expression but ignores the
+return value.
+
+.. _loopcontrols-extension:
+
+Loop Controls
+-------------
+
+**Import name:** `jinja2.ext.loopcontrols`
+
+This extension adds support for `break` and `continue` in loops. After
+enabling, Jinja2 provides those two keywords which work exactly like in
+Python.
+
+.. _with-extension:
+
+With Statement
+--------------
+
+**Import name:** `jinja2.ext.with_`
+
+.. versionadded:: 2.3
+
+This extension adds support for the with keyword. Using this keyword it
+is possible to enforce a nested scope in a template. Variables can be
+declared directly in the opening block of the with statement or using a
+standard `set` statement directly within.
+
+.. _autoescape-extension:
+
+Autoescape Extension
+--------------------
+
+**Import name:** `jinja2.ext.autoescape`
+
+.. versionadded:: 2.4
+
+The autoescape extension allows you to toggle the autoescape feature from
+within the template. If the environment's :attr:`~Environment.autoescape`
+setting is set to `False` it can be activated, if it's `True` it can be
+deactivated. The setting overriding is scoped.
+
+
+.. _writing-extensions:
+
+Writing Extensions
+------------------
+
+.. module:: jinja2.ext
+
+By writing extensions you can add custom tags to Jinja2. This is a non-trivial
+task and usually not needed as the default tags and expressions cover all
+common use cases. The i18n extension is a good example of why extensions are
+useful. Another one would be fragment caching.
+
+When writing extensions you have to keep in mind that you are working with the
+Jinja2 template compiler which does not validate the node tree you are passing
+to it. If the AST is malformed you will get all kinds of compiler or runtime
+errors that are horrible to debug. Always make sure you are using the nodes
+you create correctly. The API documentation below shows which nodes exist and
+how to use them.
+
+Example Extension
+~~~~~~~~~~~~~~~~~
+
+The following example implements a `cache` tag for Jinja2 by using the
+`Werkzeug`_ caching contrib module:
+
+.. literalinclude:: cache_extension.py
+ :language: python
+
+And here is how you use it in an environment::
+
+ from jinja2 import Environment
+ from werkzeug.contrib.cache import SimpleCache
+
+ env = Environment(extensions=[FragmentCacheExtension])
+ env.fragment_cache = SimpleCache()
+
+Inside the template it's then possible to mark blocks as cacheable. The
+following example caches a sidebar for 300 seconds:
+
+.. sourcecode:: html+jinja
+
+ {% cache 'sidebar', 300 %}
+ <div class="sidebar">
+ ...
+ </div>
+ {% endcache %}
+
+.. _Werkzeug: http://werkzeug.pocoo.org/
+
+Extension API
+~~~~~~~~~~~~~
+
+Extensions always have to extend the :class:`jinja2.ext.Extension` class:
+
+.. autoclass:: Extension
+ :members: preprocess, filter_stream, parse, attr, call_method
+
+ .. attribute:: identifier
+
+ The identifier of the extension. This is always the true import name
+ of the extension class and must not be changed.
+
+ .. attribute:: tags
+
+ If the extension implements custom tags this is a set of tag names
+ the extension is listening for.
+
+Parser API
+~~~~~~~~~~
+
+The parser passed to :meth:`Extension.parse` provides ways to parse
+expressions of different types. The following methods may be used by
+extensions:
+
+.. autoclass:: jinja2.parser.Parser
+ :members: parse_expression, parse_tuple, parse_assign_target,
+ parse_statements, free_identifier, fail
+
+ .. attribute:: filename
+
+ The filename of the template the parser processes. This is **not**
+ the load name of the template. For the load name see :attr:`name`.
+ For templates that were not loaded form the file system this is
+ `None`.
+
+ .. attribute:: name
+
+ The load name of the template.
+
+ .. attribute:: stream
+
+ The current :class:`~jinja2.lexer.TokenStream`
+
+.. autoclass:: jinja2.lexer.TokenStream
+ :members: push, look, eos, skip, next, next_if, skip_if, expect
+
+ .. attribute:: current
+
+ The current :class:`~jinja2.lexer.Token`.
+
+.. autoclass:: jinja2.lexer.Token
+ :members: test, test_any
+
+ .. attribute:: lineno
+
+ The line number of the token
+
+ .. attribute:: type
+
+ The type of the token. This string is interned so you may compare
+ it with arbitrary strings using the `is` operator.
+
+ .. attribute:: value
+
+ The value of the token.
+
+There is also a utility function in the lexer module that can count newline
+characters in strings:
+
+.. autofunction:: jinja2.lexer.count_newlines
+
+AST
+~~~
+
+The AST (Abstract Syntax Tree) is used to represent a template after parsing.
+It's build of nodes that the compiler then converts into executable Python
+code objects. Extensions that provide custom statements can return nodes to
+execute custom Python code.
+
+The list below describes all nodes that are currently available. The AST may
+change between Jinja2 versions but will stay backwards compatible.
+
+For more information have a look at the repr of :meth:`jinja2.Environment.parse`.
+
+.. module:: jinja2.nodes
+
+.. jinjanodes::
+
+.. autoexception:: Impossible
diff --git a/deps/v8_inspector/deps/jinja2/docs/faq.rst b/deps/v8_inspector/deps/jinja2/docs/faq.rst
new file mode 100644
index 0000000000..0b0375e190
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/faq.rst
@@ -0,0 +1,191 @@
+Frequently Asked Questions
+==========================
+
+This page answers some of the often asked questions about Jinja.
+
+.. highlight:: html+jinja
+
+Why is it called Jinja?
+-----------------------
+
+The name Jinja was chosen because it's the name of a Japanese temple and
+temple and template share a similar pronunciation. It is not named after
+the city in Uganda.
+
+How fast is it?
+---------------
+
+We really hate benchmarks especially since they don't reflect much. The
+performance of a template depends on many factors and you would have to
+benchmark different engines in different situations. The benchmarks from the
+testsuite show that Jinja2 has a similar performance to `Mako`_ and is between
+10 and 20 times faster than Django's template engine or Genshi. These numbers
+should be taken with tons of salt as the benchmarks that took these numbers
+only test a few performance related situations such as looping. Generally
+speaking the performance of a template engine doesn't matter much as the
+usual bottleneck in a web application is either the database or the application
+code.
+
+.. _Mako: http://www.makotemplates.org/
+
+How Compatible is Jinja2 with Django?
+-------------------------------------
+
+The default syntax of Jinja2 matches Django syntax in many ways. However
+this similarity doesn't mean that you can use a Django template unmodified
+in Jinja2. For example filter arguments use a function call syntax rather
+than a colon to separate filter name and arguments. Additionally the
+extension interface in Jinja is fundamentally different from the Django one
+which means that your custom tags won't work any longer.
+
+Generally speaking you will use much less custom extensions as the Jinja
+template system allows you to use a certain subset of Python expressions
+which can replace most Django extensions. For example instead of using
+something like this::
+
+ {% load comments %}
+ {% get_latest_comments 10 as latest_comments %}
+ {% for comment in latest_comments %}
+ ...
+ {% endfor %}
+
+You will most likely provide an object with attributes to retrieve
+comments from the database::
+
+ {% for comment in models.comments.latest(10) %}
+ ...
+ {% endfor %}
+
+Or directly provide the model for quick testing::
+
+ {% for comment in Comment.objects.order_by('-pub_date')[:10] %}
+ ...
+ {% endfor %}
+
+Please keep in mind that even though you may put such things into templates
+it still isn't a good idea. Queries should go into the view code and not
+the template!
+
+Isn't it a terrible idea to put Logic into Templates?
+-----------------------------------------------------
+
+Without a doubt you should try to remove as much logic from templates as
+possible. But templates without any logic mean that you have to do all
+the processing in the code which is boring and stupid. A template engine
+that does that is shipped with Python and called `string.Template`. Comes
+without loops and if conditions and is by far the fastest template engine
+you can get for Python.
+
+So some amount of logic is required in templates to keep everyone happy.
+And Jinja leaves it pretty much to you how much logic you want to put into
+templates. There are some restrictions in what you can do and what not.
+
+Jinja2 neither allows you to put arbitrary Python code into templates nor
+does it allow all Python expressions. The operators are limited to the
+most common ones and more advanced expressions such as list comprehensions
+and generator expressions are not supported. This keeps the template engine
+easier to maintain and templates more readable.
+
+Why is Autoescaping not the Default?
+------------------------------------
+
+There are multiple reasons why automatic escaping is not the default mode
+and also not the recommended one. While automatic escaping of variables
+means that you will less likely have an XSS problem it also causes a huge
+amount of extra processing in the template engine which can cause serious
+performance problems. As Python doesn't provide a way to mark strings as
+unsafe Jinja has to hack around that limitation by providing a custom
+string class (the :class:`Markup` string) that safely interacts with safe
+and unsafe strings.
+
+With explicit escaping however the template engine doesn't have to perform
+any safety checks on variables. Also a human knows not to escape integers
+or strings that may never contain characters one has to escape or already
+HTML markup. For example when iterating over a list over a table of
+integers and floats for a table of statistics the template designer can
+omit the escaping because he knows that integers or floats don't contain
+any unsafe parameters.
+
+Additionally Jinja2 is a general purpose template engine and not only used
+for HTML/XML generation. For example you may generate LaTeX, emails,
+CSS, JavaScript, or configuration files.
+
+Why is the Context immutable?
+-----------------------------
+
+When writing a :func:`contextfunction` or something similar you may have
+noticed that the context tries to stop you from modifying it. If you have
+managed to modify the context by using an internal context API you may
+have noticed that changes in the context don't seem to be visible in the
+template. The reason for this is that Jinja uses the context only as
+primary data source for template variables for performance reasons.
+
+If you want to modify the context write a function that returns a variable
+instead that one can assign to a variable by using set::
+
+ {% set comments = get_latest_comments() %}
+
+My tracebacks look weird. What's happening?
+--------------------------------------------
+
+If the debugsupport module is not compiled and you are using a Python
+installation without ctypes (Python 2.4 without ctypes, Jython or Google's
+AppEngine) Jinja2 is unable to provide correct debugging information and
+the traceback may be incomplete. There is currently no good workaround
+for Jython or the AppEngine as ctypes is unavailable there and it's not
+possible to use the debugsupport extension.
+
+If you are working in the Google AppEngine development server you can
+whitelist the ctypes module to restore the tracebacks. This however won't
+work in production environments::
+
+ import os
+ if os.environ.get('SERVER_SOFTWARE', '').startswith('Dev'):
+ from google.appengine.tools.dev_appserver import HardenedModulesHook
+ HardenedModulesHook._WHITE_LIST_C_MODULES += ['_ctypes', 'gestalt']
+
+Credit for this snippet goes to `Thomas Johansson
+<http://stackoverflow.com/questions/3086091/debug-jinja2-in-google-app-engine/3694434#3694434>`_
+
+Why is there no Python 2.3/2.4/2.5/3.1/3.2 support?
+---------------------------------------------------
+
+Python 2.3 is missing a lot of features that are used heavily in Jinja2. This
+decision was made as with the upcoming Python 2.6 and 3.0 versions it becomes
+harder to maintain the code for older Python versions. If you really need
+Python 2.3 support you either have to use `Jinja 1`_ or other templating
+engines that still support 2.3.
+
+Python 2.4/2.5/3.1/3.2 support was removed when we switched to supporting
+Python 2 and 3 by the same sourcecode (without using 2to3). It was required to
+drop support because only Python 2.6/2.7 and >=3.3 support byte and unicode
+literals in a way compatible to each other version. If you really need support
+for older Python 2 (or 3) versions, you can just use Jinja2 2.6.
+
+My Macros are overridden by something
+-------------------------------------
+
+In some situations the Jinja scoping appears arbitrary:
+
+layout.tmpl:
+
+.. sourcecode:: jinja
+
+ {% macro foo() %}LAYOUT{% endmacro %}
+ {% block body %}{% endblock %}
+
+child.tmpl:
+
+.. sourcecode:: jinja
+
+ {% extends 'layout.tmpl' %}
+ {% macro foo() %}CHILD{% endmacro %}
+ {% block body %}{{ foo() }}{% endblock %}
+
+This will print ``LAYOUT`` in Jinja2. This is a side effect of having
+the parent template evaluated after the child one. This allows child
+templates passing information to the parent template. To avoid this
+issue rename the macro or variable in the parent template to have an
+uncommon prefix.
+
+.. _Jinja 1: http://jinja.pocoo.org/1/
diff --git a/deps/v8_inspector/deps/jinja2/docs/index.rst b/deps/v8_inspector/deps/jinja2/docs/index.rst
new file mode 100644
index 0000000000..a08d6281df
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/index.rst
@@ -0,0 +1,34 @@
+Welcome to Jinja2
+=================
+
+Jinja2 is a modern and designer-friendly templating language for Python,
+modelled after Django's templates. It is fast, widely used and secure
+with the optional sandboxed template execution environment:
+
+.. sourcecode:: html+jinja
+
+ <title>{% block title %}{% endblock %}</title>
+ <ul>
+ {% for user in users %}
+ <li><a href="{{ user.url }}">{{ user.username }}</a></li>
+ {% endfor %}
+ </ul>
+
+**Features:**
+
+- sandboxed execution
+- powerful automatic HTML escaping system for XSS prevention
+- template inheritance
+- compiles down to the optimal python code just in time
+- optional ahead-of-time template compilation
+- easy to debug. Line numbers of exceptions directly point to
+ the correct line in the template.
+- configurable syntax
+
+.. include:: contents.rst.inc
+
+If you can't find the information you're looking for, have a look at the
+index or try to find it using the search function:
+
+* :ref:`genindex`
+* :ref:`search`
diff --git a/deps/v8_inspector/deps/jinja2/docs/integration.rst b/deps/v8_inspector/deps/jinja2/docs/integration.rst
new file mode 100644
index 0000000000..92a3b14794
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/integration.rst
@@ -0,0 +1,101 @@
+Integration
+===========
+
+Jinja2 provides some code for integration into other tools such as frameworks,
+the `Babel`_ library or your favourite editor for fancy code highlighting.
+This is a brief description of whats included.
+
+Files to help integration are available
+`here. <https://github.com/mitsuhiko/jinja2/tree/master/ext>`_
+
+.. _babel-integration:
+
+Babel Integration
+-----------------
+
+Jinja provides support for extracting gettext messages from templates via a
+`Babel`_ extractor entry point called `jinja2.ext.babel_extract`. The Babel
+support is implemented as part of the :ref:`i18n-extension` extension.
+
+Gettext messages extracted from both `trans` tags and code expressions.
+
+To extract gettext messages from templates, the project needs a Jinja2 section
+in its Babel extraction method `mapping file`_:
+
+.. sourcecode:: ini
+
+ [jinja2: **/templates/**.html]
+ encoding = utf-8
+
+The syntax related options of the :class:`Environment` are also available as
+configuration values in the mapping file. For example to tell the extraction
+that templates use ``%`` as `line_statement_prefix` you can use this code:
+
+.. sourcecode:: ini
+
+ [jinja2: **/templates/**.html]
+ encoding = utf-8
+ line_statement_prefix = %
+
+:ref:`jinja-extensions` may also be defined by passing a comma separated list
+of import paths as `extensions` value. The i18n extension is added
+automatically.
+
+.. versionchanged:: 2.7
+
+ Until 2.7 template syntax errors were always ignored. This was done
+ since many people are dropping non template html files into the
+ templates folder and it would randomly fail. The assumption was that
+ testsuites will catch syntax errors in templates anyways. If you don't
+ want that behavior you can add ``silent=false`` to the settings and
+ exceptions are propagated.
+
+.. _mapping file: http://babel.edgewall.org/wiki/Documentation/messages.html#extraction-method-mapping-and-configuration
+
+Pylons
+------
+
+With `Pylons`_ 0.9.7 onwards it's incredible easy to integrate Jinja into a
+Pylons powered application.
+
+The template engine is configured in `config/environment.py`. The configuration
+for Jinja2 looks something like that::
+
+ from jinja2 import Environment, PackageLoader
+ config['pylons.app_globals'].jinja_env = Environment(
+ loader=PackageLoader('yourapplication', 'templates')
+ )
+
+After that you can render Jinja templates by using the `render_jinja` function
+from the `pylons.templating` module.
+
+Additionally it's a good idea to set the Pylons' `c` object into strict mode.
+Per default any attribute to not existing attributes on the `c` object return
+an empty string and not an undefined object. To change this just use this
+snippet and add it into your `config/environment.py`::
+
+ config['pylons.strict_c'] = True
+
+.. _Pylons: http://www.pylonshq.com/
+
+TextMate
+--------
+
+There is a bundle for TextMate that supports syntax highlighting for Jinja1 and Jinja2 for text based
+templates as well as HTML. It also contains a few often used snippets.
+
+.. _TextMate Bundle: https://github.com/mitsuhiko/jinja2-tmbundle
+
+Vim
+---
+
+A syntax plugin for `Vim`_ exists in the Vim-scripts directory as well as the
+`ext` folder at the root of the Jinja2 project. `The script
+<http://www.vim.org/scripts/script.php?script_id=1856>`_ supports Jinja1 and
+Jinja2. Once installed two file types are available `jinja` and `htmljinja`.
+The first one for text based templates, the latter for HTML templates.
+
+Copy the files into your `syntax` folder.
+
+.. _Babel: http://babel.edgewall.org/
+.. _Vim: http://www.vim.org/
diff --git a/deps/v8_inspector/deps/jinja2/docs/intro.rst b/deps/v8_inspector/deps/jinja2/docs/intro.rst
new file mode 100644
index 0000000000..b6da5ea5f1
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/intro.rst
@@ -0,0 +1,123 @@
+Introduction
+============
+
+This is the documentation for the Jinja2 general purpose templating language.
+Jinja2 is a library for Python that is designed to be flexible, fast and secure.
+
+If you have any exposure to other text-based template languages, such as Smarty or
+Django, you should feel right at home with Jinja2. It's both designer and
+developer friendly by sticking to Python's principles and adding functionality
+useful for templating environments.
+
+Prerequisites
+-------------
+
+Jinja2 works with Python 2.6.x, 2.7.x and >= 3.3. If you are using Python
+3.2 you can use an older release of Jinja2 (2.6) as support for Python 3.2
+was dropped in Jinja2 version 2.7.
+
+If you wish to use the :class:`~jinja2.PackageLoader` class, you will also
+need `setuptools`_ or `distribute`_ installed at runtime.
+
+Installation
+------------
+
+You have multiple ways to install Jinja2. If you are unsure what to do, go
+with the Python egg or tarball.
+
+As a Python egg (via `easy_install`)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can install the most recent Jinja2 version using `easy_install`_ or `pip`_::
+
+ easy_install Jinja2
+ pip install Jinja2
+
+This will install a Jinja2 egg in your Python installation's site-packages
+directory.
+
+(If you are installing from the Windows command line omit the `sudo` and make
+sure to run the command as user with administrator rights)
+
+From the tarball release
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1. Download the most recent tarball from the `download page`_
+2. Unpack the tarball
+3. ``sudo python setup.py install``
+
+Note that you either have to have `setuptools` or `distribute` installed;
+the latter is preferred.
+
+This will install Jinja2 into your Python installation's site-packages directory.
+
+Installing the development version
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1. Install `git`_
+2. ``git clone git://github.com/mitsuhiko/jinja2.git``
+3. ``cd jinja2``
+4. ``ln -s jinja2 /usr/lib/python2.X/site-packages``
+
+As an alternative to steps 4 you can also do ``python setup.py develop``
+which will install the package via `distribute` in development mode. This also
+has the advantage that the C extensions are compiled.
+
+.. _download page: http://pypi.python.org/pypi/Jinja2
+.. _distribute: http://pypi.python.org/pypi/distribute
+.. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools
+.. _easy_install: http://peak.telecommunity.com/DevCenter/EasyInstall
+.. _pip: http://pypi.python.org/pypi/pip
+.. _git: http://git-scm.org/
+
+
+MarkupSafe Dependency
+~~~~~~~~~~~~~~~~~~~~~
+
+As of version 2.7 Jinja2 depends on the `MarkupSafe`_ module. If you
+install Jinja2 via `pip` or `easy_install` it will be installed
+automatically for you.
+
+.. _MarkupSafe: http://pypi.python.org/pypi/MarkupSafe
+
+Basic API Usage
+---------------
+
+This section gives you a brief introduction to the Python API for Jinja2
+templates.
+
+The most basic way to create a template and render it is through
+:class:`~jinja2.Template`. This however is not the recommended way to
+work with it if your templates are not loaded from strings but the file
+system or another data source:
+
+>>> from jinja2 import Template
+>>> template = Template('Hello {{ name }}!')
+>>> template.render(name='John Doe')
+u'Hello John Doe!'
+
+By creating an instance of :class:`~jinja2.Template` you get back a new template
+object that provides a method called :meth:`~jinja2.Template.render` which when
+called with a dict or keyword arguments expands the template. The dict
+or keywords arguments passed to the template are the so-called "context"
+of the template.
+
+What you can see here is that Jinja2 is using unicode internally and the
+return value is an unicode string. So make sure that your application is
+indeed using unicode internally.
+
+
+Experimental Python 3 Support
+-----------------------------
+
+Jinja 2.7 brings experimental support for Python >=3.3. It means that all
+unittests pass on the new version, but there might still be small bugs in
+there and behavior might be inconsistent. If you notice any bugs, please
+provide feedback in the `Jinja bug tracker`_.
+
+Also please keep in mind that the documentation is written with Python 2
+in mind, so you will have to adapt the shown code examples to Python 3 syntax
+for yourself.
+
+
+.. _Jinja bug tracker: http://github.com/mitsuhiko/jinja2/issues
diff --git a/deps/v8_inspector/deps/jinja2/docs/jinjaext.py b/deps/v8_inspector/deps/jinja2/docs/jinjaext.py
new file mode 100644
index 0000000000..cdacba9d9c
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/jinjaext.py
@@ -0,0 +1,194 @@
+# -*- coding: utf-8 -*-
+"""
+ Jinja Documentation Extensions
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Support for automatically documenting filters and tests.
+
+ :copyright: Copyright 2008 by Armin Ronacher.
+ :license: BSD.
+"""
+import collections
+import os
+import re
+import inspect
+import jinja2
+from itertools import islice
+from types import BuiltinFunctionType
+from docutils import nodes
+from docutils.statemachine import ViewList
+from sphinx.ext.autodoc import prepare_docstring
+from sphinx.application import TemplateBridge
+from pygments.style import Style
+from pygments.token import Keyword, Name, Comment, String, Error, \
+ Number, Operator, Generic
+from jinja2 import Environment, FileSystemLoader
+
+
+def parse_rst(state, content_offset, doc):
+ node = nodes.section()
+ # hack around title style bookkeeping
+ surrounding_title_styles = state.memo.title_styles
+ surrounding_section_level = state.memo.section_level
+ state.memo.title_styles = []
+ state.memo.section_level = 0
+ state.nested_parse(doc, content_offset, node, match_titles=1)
+ state.memo.title_styles = surrounding_title_styles
+ state.memo.section_level = surrounding_section_level
+ return node.children
+
+
+class JinjaStyle(Style):
+ title = 'Jinja Style'
+ default_style = ""
+ styles = {
+ Comment: 'italic #aaaaaa',
+ Comment.Preproc: 'noitalic #B11414',
+ Comment.Special: 'italic #505050',
+
+ Keyword: 'bold #B80000',
+ Keyword.Type: '#808080',
+
+ Operator.Word: 'bold #B80000',
+
+ Name.Builtin: '#333333',
+ Name.Function: '#333333',
+ Name.Class: 'bold #333333',
+ Name.Namespace: 'bold #333333',
+ Name.Entity: 'bold #363636',
+ Name.Attribute: '#686868',
+ Name.Tag: 'bold #686868',
+ Name.Decorator: '#686868',
+
+ String: '#AA891C',
+ Number: '#444444',
+
+ Generic.Heading: 'bold #000080',
+ Generic.Subheading: 'bold #800080',
+ Generic.Deleted: '#aa0000',
+ Generic.Inserted: '#00aa00',
+ Generic.Error: '#aa0000',
+ Generic.Emph: 'italic',
+ Generic.Strong: 'bold',
+ Generic.Prompt: '#555555',
+ Generic.Output: '#888888',
+ Generic.Traceback: '#aa0000',
+
+ Error: '#F00 bg:#FAA'
+ }
+
+
+_sig_re = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*(\(.*?\))')
+
+
+def format_function(name, aliases, func):
+ lines = inspect.getdoc(func).splitlines()
+ signature = '()'
+ if isinstance(func, BuiltinFunctionType):
+ match = _sig_re.match(lines[0])
+ if match is not None:
+ del lines[:1 + bool(lines and not lines[0])]
+ signature = match.group(1)
+ else:
+ try:
+ argspec = inspect.getargspec(func)
+ if getattr(func, 'environmentfilter', False) or \
+ getattr(func, 'contextfilter', False) or \
+ getattr(func, 'evalcontextfilter', False):
+ del argspec[0][0]
+ signature = inspect.formatargspec(*argspec)
+ except:
+ pass
+ result = ['.. function:: %s%s' % (name, signature), '']
+ result.extend(' ' + line for line in lines)
+ if aliases:
+ result.extend(('', ' :aliases: %s' % ', '.join(
+ '``%s``' % x for x in sorted(aliases))))
+ return result
+
+
+def dump_functions(mapping):
+ def directive(dirname, arguments, options, content, lineno,
+ content_offset, block_text, state, state_machine):
+ reverse_mapping = {}
+ for name, func in mapping.items():
+ reverse_mapping.setdefault(func, []).append(name)
+ filters = []
+ for func, names in reverse_mapping.items():
+ aliases = sorted(names, key=lambda x: len(x))
+ name = aliases.pop()
+ filters.append((name, aliases, func))
+ filters.sort()
+
+ result = ViewList()
+ for name, aliases, func in filters:
+ for item in format_function(name, aliases, func):
+ result.append(item, '<jinjaext>')
+
+ node = nodes.paragraph()
+ state.nested_parse(result, content_offset, node)
+ return node.children
+ return directive
+
+
+from jinja2.defaults import DEFAULT_FILTERS, DEFAULT_TESTS
+jinja_filters = dump_functions(DEFAULT_FILTERS)
+jinja_tests = dump_functions(DEFAULT_TESTS)
+
+
+def jinja_nodes(dirname, arguments, options, content, lineno,
+ content_offset, block_text, state, state_machine):
+ from jinja2.nodes import Node
+ doc = ViewList()
+ def walk(node, indent):
+ p = ' ' * indent
+ sig = ', '.join(node.fields)
+ doc.append(p + '.. autoclass:: %s(%s)' % (node.__name__, sig), '')
+ if node.abstract:
+ members = []
+ for key, name in node.__dict__.items():
+ if not key.startswith('_') and \
+ not hasattr(node.__base__, key) and isinstance(name, collections.Callable):
+ members.append(key)
+ if members:
+ members.sort()
+ doc.append('%s :members: %s' % (p, ', '.join(members)), '')
+ if node.__base__ != object:
+ doc.append('', '')
+ doc.append('%s :Node type: :class:`%s`' %
+ (p, node.__base__.__name__), '')
+ doc.append('', '')
+ children = node.__subclasses__()
+ children.sort(key=lambda x: x.__name__.lower())
+ for child in children:
+ walk(child, indent)
+ walk(Node, 0)
+ return parse_rst(state, content_offset, doc)
+
+
+def inject_toc(app, doctree, docname):
+ titleiter = iter(doctree.traverse(nodes.title))
+ try:
+ # skip first title, we are not interested in that one
+ next(titleiter)
+ title = next(titleiter)
+ # and check if there is at least another title
+ next(titleiter)
+ except StopIteration:
+ return
+ tocnode = nodes.section('')
+ tocnode['classes'].append('toc')
+ toctitle = nodes.section('')
+ toctitle['classes'].append('toctitle')
+ toctitle.append(nodes.title(text='Table Of Contents'))
+ tocnode.append(toctitle)
+ tocnode += doctree.document.settings.env.get_toc_for(docname)[0][1]
+ title.parent.insert(title.parent.children.index(title), tocnode)
+
+
+def setup(app):
+ app.add_directive('jinjafilters', jinja_filters, 0, (0, 0, 0))
+ app.add_directive('jinjatests', jinja_tests, 0, (0, 0, 0))
+ app.add_directive('jinjanodes', jinja_nodes, 0, (0, 0, 0))
+ # uncomment for inline toc. links are broken unfortunately
+ ##app.connect('doctree-resolved', inject_toc)
diff --git a/deps/v8_inspector/deps/jinja2/docs/jinjastyle.sty b/deps/v8_inspector/deps/jinja2/docs/jinjastyle.sty
new file mode 100644
index 0000000000..e93c8d1c69
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/jinjastyle.sty
@@ -0,0 +1,119 @@
+\definecolor{TitleColor}{rgb}{0,0,0}
+\definecolor{InnerLinkColor}{rgb}{0,0,0}
+\definecolor{OuterLinkColor}{rgb}{0.8,0,0}
+
+\renewcommand{\maketitle}{%
+ \begin{titlepage}%
+ \let\footnotesize\small
+ \let\footnoterule\relax
+ \ifsphinxpdfoutput
+ \begingroup
+ % This \def is required to deal with multi-line authors; it
+ % changes \\ to ', ' (comma-space), making it pass muster for
+ % generating document info in the PDF file.
+ \def\\{, }
+ \pdfinfo{
+ /Author (\@author)
+ /Title (\@title)
+ }
+ \endgroup
+ \fi
+ \begin{flushright}%
+ %\sphinxlogo%
+ {\center
+ \vspace*{3cm}
+ \includegraphics{logo.pdf}
+ \vspace{3cm}
+ \par
+ {\rm\Huge \@title \par}%
+ {\em\LARGE \py@release\releaseinfo \par}
+ {\large
+ \@date \par
+ \py@authoraddress \par
+ }}%
+ \end{flushright}%\par
+ \@thanks
+ \end{titlepage}%
+ \cleardoublepage%
+ \setcounter{footnote}{0}%
+ \let\thanks\relax\let\maketitle\relax
+ %\gdef\@thanks{}\gdef\@author{}\gdef\@title{}
+}
+
+\fancypagestyle{normal}{
+ \fancyhf{}
+ \fancyfoot[LE,RO]{{\thepage}}
+ \fancyfoot[LO]{{\nouppercase{\rightmark}}}
+ \fancyfoot[RE]{{\nouppercase{\leftmark}}}
+ \fancyhead[LE,RO]{{ \@title, \py@release}}
+ \renewcommand{\headrulewidth}{0.4pt}
+ \renewcommand{\footrulewidth}{0.4pt}
+}
+
+\fancypagestyle{plain}{
+ \fancyhf{}
+ \fancyfoot[LE,RO]{{\thepage}}
+ \renewcommand{\headrulewidth}{0pt}
+ \renewcommand{\footrulewidth}{0.4pt}
+}
+
+\titleformat{\section}{\Large}%
+ {\py@TitleColor\thesection}{0.5em}{\py@TitleColor}{\py@NormalColor}
+\titleformat{\subsection}{\large}%
+ {\py@TitleColor\thesubsection}{0.5em}{\py@TitleColor}{\py@NormalColor}
+\titleformat{\subsubsection}{}%
+ {\py@TitleColor\thesubsubsection}{0.5em}{\py@TitleColor}{\py@NormalColor}
+\titleformat{\paragraph}{\large}%
+ {\py@TitleColor}{0em}{\py@TitleColor}{\py@NormalColor}
+
+\ChNameVar{\raggedleft\normalsize}
+\ChNumVar{\raggedleft \bfseries\Large}
+\ChTitleVar{\raggedleft \rm\Huge}
+
+\renewcommand\thepart{\@Roman\c@part}
+\renewcommand\part{%
+ \pagestyle{plain}
+ \if@noskipsec \leavevmode \fi
+ \cleardoublepage
+ \vspace*{6cm}%
+ \@afterindentfalse
+ \secdef\@part\@spart}
+
+\def\@part[#1]#2{%
+ \ifnum \c@secnumdepth >\m@ne
+ \refstepcounter{part}%
+ \addcontentsline{toc}{part}{\thepart\hspace{1em}#1}%
+ \else
+ \addcontentsline{toc}{part}{#1}%
+ \fi
+ {\parindent \z@ %\center
+ \interlinepenalty \@M
+ \normalfont
+ \ifnum \c@secnumdepth >\m@ne
+ \rm\Large \partname~\thepart
+ \par\nobreak
+ \fi
+ \MakeUppercase{\rm\Huge #2}%
+ \markboth{}{}\par}%
+ \nobreak
+ \vskip 8ex
+ \@afterheading}
+\def\@spart#1{%
+ {\parindent \z@ %\center
+ \interlinepenalty \@M
+ \normalfont
+ \huge \bfseries #1\par}%
+ \nobreak
+ \vskip 3ex
+ \@afterheading}
+
+% use inconsolata font
+\usepackage{inconsolata}
+
+% fix single quotes, for inconsolata. (does not work)
+%%\usepackage{textcomp}
+%%\begingroup
+%% \catcode`'=\active
+%% \g@addto@macro\@noligs{\let'\textsinglequote}
+%% \endgroup
+%%\endinput
diff --git a/deps/v8_inspector/deps/jinja2/docs/latexindex.rst b/deps/v8_inspector/deps/jinja2/docs/latexindex.rst
new file mode 100644
index 0000000000..300e60d10f
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/latexindex.rst
@@ -0,0 +1,6 @@
+:orphan:
+
+Jinja2 Documentation
+====================
+
+.. include:: contents.rst.inc
diff --git a/deps/v8_inspector/deps/jinja2/docs/logo.pdf b/deps/v8_inspector/deps/jinja2/docs/logo.pdf
new file mode 100644
index 0000000000..3e8a9cf480
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/logo.pdf
Binary files differ
diff --git a/deps/v8_inspector/deps/jinja2/docs/sandbox.rst b/deps/v8_inspector/deps/jinja2/docs/sandbox.rst
new file mode 100644
index 0000000000..71ccc0d6de
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/sandbox.rst
@@ -0,0 +1,94 @@
+Sandbox
+=======
+
+The Jinja2 sandbox can be used to evaluate untrusted code. Access to unsafe
+attributes and methods is prohibited.
+
+Assuming `env` is a :class:`SandboxedEnvironment` in the default configuration
+the following piece of code shows how it works:
+
+>>> env.from_string("{{ func.func_code }}").render(func=lambda:None)
+u''
+>>> env.from_string("{{ func.func_code.do_something }}").render(func=lambda:None)
+Traceback (most recent call last):
+ ...
+SecurityError: access to attribute 'func_code' of 'function' object is unsafe.
+
+API
+---
+
+.. module:: jinja2.sandbox
+
+.. autoclass:: SandboxedEnvironment([options])
+ :members: is_safe_attribute, is_safe_callable, default_binop_table,
+ default_unop_table, intercepted_binops, intercepted_unops,
+ call_binop, call_unop
+
+.. autoclass:: ImmutableSandboxedEnvironment([options])
+
+.. autoexception:: SecurityError
+
+.. autofunction:: unsafe
+
+.. autofunction:: is_internal_attribute
+
+.. autofunction:: modifies_known_mutable
+
+.. admonition:: Note
+
+ The Jinja2 sandbox alone is no solution for perfect security. Especially
+ for web applications you have to keep in mind that users may create
+ templates with arbitrary HTML in so it's crucial to ensure that (if you
+ are running multiple users on the same server) they can't harm each other
+ via JavaScript insertions and much more.
+
+ Also the sandbox is only as good as the configuration. We strongly
+ recommend only passing non-shared resources to the template and use
+ some sort of whitelisting for attributes.
+
+ Also keep in mind that templates may raise runtime or compile time errors,
+ so make sure to catch them.
+
+Operator Intercepting
+---------------------
+
+.. versionadded:: 2.6
+
+For maximum performance Jinja2 will let operators call directly the type
+specific callback methods. This means that it's not possible to have this
+intercepted by overriding :meth:`Environment.call`. Furthermore a
+conversion from operator to special method is not always directly possible
+due to how operators work. For instance for divisions more than one
+special method exist.
+
+With Jinja 2.6 there is now support for explicit operator intercepting.
+This can be used to customize specific operators as necessary. In order
+to intercept an operator one has to override the
+:attr:`SandboxedEnvironment.intercepted_binops` attribute. Once the
+operator that needs to be intercepted is added to that set Jinja2 will
+generate bytecode that calls the :meth:`SandboxedEnvironment.call_binop`
+function. For unary operators the `unary` attributes and methods have to
+be used instead.
+
+The default implementation of :attr:`SandboxedEnvironment.call_binop`
+will use the :attr:`SandboxedEnvironment.binop_table` to translate
+operator symbols into callbacks performing the default operator behavior.
+
+This example shows how the power (``**``) operator can be disabled in
+Jinja2::
+
+ from jinja2.sandbox import SandboxedEnvironment
+
+
+ class MyEnvironment(SandboxedEnvironment):
+ intercepted_binops = frozenset(['**'])
+
+ def call_binop(self, context, operator, left, right):
+ if operator == '**':
+ return self.undefined('the power operator is unavailable')
+ return SandboxedEnvironment.call_binop(self, context,
+ operator, left, right)
+
+Make sure to always call into the super method, even if you are not
+intercepting the call. Jinja2 might internally call the method to
+evaluate expressions.
diff --git a/deps/v8_inspector/deps/jinja2/docs/switching.rst b/deps/v8_inspector/deps/jinja2/docs/switching.rst
new file mode 100644
index 0000000000..01a7d0d787
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/switching.rst
@@ -0,0 +1,226 @@
+Switching from other Template Engines
+=====================================
+
+.. highlight:: html+jinja
+
+If you have used a different template engine in the past and want to switch
+to Jinja2 here is a small guide that shows the basic syntactic and semantic
+changes between some common, similar text template engines for Python.
+
+Jinja1
+------
+
+Jinja2 is mostly compatible with Jinja1 in terms of API usage and template
+syntax. The differences between Jinja1 and 2 are explained in the following
+list.
+
+API
+~~~
+
+Loaders
+ Jinja2 uses a different loader API. Because the internal representation
+ of templates changed there is no longer support for external caching
+ systems such as memcached. The memory consumed by templates is comparable
+ with regular Python modules now and external caching doesn't give any
+ advantage. If you have used a custom loader in the past have a look at
+ the new :ref:`loader API <loaders>`.
+
+Loading templates from strings
+ In the past it was possible to generate templates from a string with the
+ default environment configuration by using `jinja.from_string`. Jinja2
+ provides a :class:`Template` class that can be used to do the same, but
+ with optional additional configuration.
+
+Automatic unicode conversion
+ Jinja1 performed automatic conversion of bytestrings in a given encoding
+ into unicode objects. This conversion is no longer implemented as it
+ was inconsistent as most libraries are using the regular Python ASCII
+ bytestring to Unicode conversion. An application powered by Jinja2
+ *has to* use unicode internally everywhere or make sure that Jinja2 only
+ gets unicode strings passed.
+
+i18n
+ Jinja1 used custom translators for internationalization. i18n is now
+ available as Jinja2 extension and uses a simpler, more gettext friendly
+ interface and has support for babel. For more details see
+ :ref:`i18n-extension`.
+
+Internal methods
+ Jinja1 exposed a few internal methods on the environment object such
+ as `call_function`, `get_attribute` and others. While they were marked
+ as being an internal method it was possible to override them. Jinja2
+ doesn't have equivalent methods.
+
+Sandbox
+ Jinja1 was running sandbox mode by default. Few applications actually
+ used that feature so it became optional in Jinja2. For more details
+ about the sandboxed execution see :class:`SandboxedEnvironment`.
+
+Context
+ Jinja1 had a stacked context as storage for variables passed to the
+ environment. In Jinja2 a similar object exists but it doesn't allow
+ modifications nor is it a singleton. As inheritance is dynamic now
+ multiple context objects may exist during template evaluation.
+
+Filters and Tests
+ Filters and tests are regular functions now. It's no longer necessary
+ and allowed to use factory functions.
+
+
+Templates
+~~~~~~~~~
+
+Jinja2 has mostly the same syntax as Jinja1. What's different is that
+macros require parentheses around the argument list now.
+
+Additionally Jinja2 allows dynamic inheritance now and dynamic includes.
+The old helper function `rendertemplate` is gone now, `include` can be used
+instead. Includes no longer import macros and variable assignments, for
+that the new `import` tag is used. This concept is explained in the
+:ref:`import` documentation.
+
+Another small change happened in the `for`-tag. The special loop variable
+doesn't have a `parent` attribute, instead you have to alias the loop
+yourself. See :ref:`accessing-the-parent-loop` for more details.
+
+
+Django
+------
+
+If you have previously worked with Django templates, you should find
+Jinja2 very familiar. In fact, most of the syntax elements look and
+work the same.
+
+However, Jinja2 provides some more syntax elements covered in the
+documentation and some work a bit different.
+
+This section covers the template changes. As the API is fundamentally
+different we won't cover it here.
+
+Method Calls
+~~~~~~~~~~~~
+
+In Django method calls work implicitly, while Jinja requires the explicit
+Python syntax. Thus this Django code::
+
+ {% for page in user.get_created_pages %}
+ ...
+ {% endfor %}
+
+...looks like this in Jinja::
+
+ {% for page in user.get_created_pages() %}
+ ...
+ {% endfor %}
+
+This allows you to pass variables to the method, which is not possible in
+Django. This syntax is also used for macros.
+
+Filter Arguments
+~~~~~~~~~~~~~~~~
+
+Jinja2 provides more than one argument for filters. Also the syntax for
+argument passing is different. A template that looks like this in Django::
+
+ {{ items|join:", " }}
+
+looks like this in Jinja2::
+
+ {{ items|join(', ') }}
+
+It is a bit more verbose, but it allows different types of arguments -
+including variables - and more than one of them.
+
+Tests
+~~~~~
+
+In addition to filters there also are tests you can perform using the is
+operator. Here are some examples::
+
+ {% if user.user_id is odd %}
+ {{ user.username|e }} is odd
+ {% else %}
+ hmm. {{ user.username|e }} looks pretty normal
+ {% endif %}
+
+Loops
+~~~~~
+
+For loops work very similarly to Django, but notably the Jinja2 special
+variable for the loop context is called `loop`, not `forloop` as in Django.
+
+In addition, the Django `empty` argument is called `else` in Jinja2. For
+example, the Django template::
+
+ {% for item in items %}
+ {{ item }}
+ {% empty %}
+ No items!
+ {% endfor %}
+
+...looks like this in Jinja2::
+
+ {% for item in items %}
+ {{ item }}
+ {% else %}
+ No items!
+ {% endfor %}
+
+Cycle
+~~~~~
+
+The ``{% cycle %}`` tag does not exist in Jinja2; however, you can achieve the
+same output by using the `cycle` method on the loop context special variable.
+
+The following Django template::
+
+ {% for user in users %}
+ <li class="{% cycle 'odd' 'even' %}">{{ user }}</li>
+ {% endfor %}
+
+...looks like this in Jinja2::
+
+ {% for user in users %}
+ <li class="{{ loop.cycle('odd', 'even') }}">{{ user }}</li>
+ {% endfor %}
+
+There is no equivalent of ``{% cycle ... as variable %}``.
+
+
+Mako
+----
+
+.. highlight:: html+mako
+
+If you have used Mako so far and want to switch to Jinja2 you can configure
+Jinja2 to look more like Mako:
+
+.. sourcecode:: python
+
+ env = Environment('<%', '%>', '${', '}', '<%doc>', '</%doc>', '%', '##')
+
+With an environment configured like that, Jinja2 should be able to interpret
+a small subset of Mako templates. Jinja2 does not support embedded Python
+code, so you would have to move that out of the template. The syntax for defs
+(which are called macros in Jinja2) and template inheritance is different too.
+The following Mako template::
+
+ <%inherit file="layout.html" />
+ <%def name="title()">Page Title</%def>
+ <ul>
+ % for item in list:
+ <li>${item}</li>
+ % endfor
+ </ul>
+
+Looks like this in Jinja2 with the above configuration::
+
+ <% extends "layout.html" %>
+ <% block title %>Page Title<% endblock %>
+ <% block body %>
+ <ul>
+ % for item in list:
+ <li>${item}</li>
+ % endfor
+ </ul>
+ <% endblock %>
diff --git a/deps/v8_inspector/deps/jinja2/docs/templates.rst b/deps/v8_inspector/deps/jinja2/docs/templates.rst
new file mode 100644
index 0000000000..3c16924721
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/templates.rst
@@ -0,0 +1,1509 @@
+Template Designer Documentation
+===============================
+
+.. highlight:: html+jinja
+
+This document describes the syntax and semantics of the template engine and
+will be most useful as reference to those creating Jinja templates. As the
+template engine is very flexible, the configuration from the application can
+be slightly different from the code presented here in terms of delimiters and
+behavior of undefined values.
+
+
+Synopsis
+--------
+
+A Jinja template is simply a text file. Jinja can generate any text-based
+format (HTML, XML, CSV, LaTeX, etc.). A Jinja template doesn't need to have a
+specific extension: ``.html``, ``.xml``, or any other extension is just fine.
+
+A template contains **variables** and/or **expressions**, which get replaced
+with values when a template is *rendered*; and **tags**, which control the
+logic of the template. The template syntax is heavily inspired by Django and
+Python.
+
+Below is a minimal template that illustrates a few basics using the default
+Jinja configuration. We will cover the details later in this document::
+
+ <!DOCTYPE html>
+ <html lang="en">
+ <head>
+ <title>My Webpage</title>
+ </head>
+ <body>
+ <ul id="navigation">
+ {% for item in navigation %}
+ <li><a href="{{ item.href }}">{{ item.caption }}</a></li>
+ {% endfor %}
+ </ul>
+
+ <h1>My Webpage</h1>
+ {{ a_variable }}
+
+ {# a comment #}
+ </body>
+ </html>
+
+The following example shows the default configuration settings. An application
+developer can change the syntax configuration from ``{% foo %}`` to ``<% foo
+%>``, or something similar.
+
+There are a few kinds of delimiters. The default Jinja delimiters are
+configured as follows:
+
+* ``{% ... %}`` for :ref:`Statements <list-of-control-structures>`
+* ``{{ ... }}`` for :ref:`Expressions` to print to the template output
+* ``{# ... #}`` for :ref:`Comments` not included in the template output
+* ``# ... ##`` for :ref:`Line Statements <line-statements>`
+
+
+.. _variables:
+
+Variables
+---------
+
+Template variables are defined by the context dictionary passed to the
+template.
+
+You can mess around with the variables in templates provided they are passed in
+by the application. Variables may have attributes or elements on them you can
+access too. What attributes a variable has depends heavily on the application
+providing that variable.
+
+You can use a dot (``.``) to access attributes of a variable in addition
+to the standard Python ``__getitem__`` "subscript" syntax (``[]``).
+
+The following lines do the same thing::
+
+ {{ foo.bar }}
+ {{ foo['bar'] }}
+
+It's important to know that the outer double-curly braces are *not* part of the
+variable, but the print statement. If you access variables inside tags don't
+put the braces around them.
+
+If a variable or attribute does not exist, you will get back an undefined
+value. What you can do with that kind of value depends on the application
+configuration: the default behavior is to evaluate to an empty string if
+printed or iterated over, and to fail for every other operation.
+
+.. _notes-on-subscriptions:
+
+.. admonition:: Implementation
+
+ For the sake of convenience, ``foo.bar`` in Jinja2 does the following
+ things on the Python layer:
+
+ - check for an attribute called `bar` on `foo`
+ (``getattr(foo, 'bar')``)
+ - if there is not, check for an item ``'bar'`` in `foo`
+ (``foo.__getitem__('bar')``)
+ - if there is not, return an undefined object.
+
+ ``foo['bar']`` works mostly the same with a small difference in sequence:
+
+ - check for an item ``'bar'`` in `foo`.
+ (``foo.__getitem__('bar')``)
+ - if there is not, check for an attribute called `bar` on `foo`.
+ (``getattr(foo, 'bar')``)
+ - if there is not, return an undefined object.
+
+ This is important if an object has an item and attribute with the same
+ name. Additionally, the :func:`attr` filter only looks up attributes.
+
+.. _filters:
+
+Filters
+-------
+
+Variables can be modified by **filters**. Filters are separated from the
+variable by a pipe symbol (``|``) and may have optional arguments in
+parentheses. Multiple filters can be chained. The output of one filter is
+applied to the next.
+
+For example, ``{{ name|striptags|title }}`` will remove all HTML Tags from
+variable `name` and title-case the output (``title(striptags(name))``).
+
+Filters that accept arguments have parentheses around the arguments, just like
+a function call. For example: ``{{ listx|join(', ') }}`` will join a list with
+commas (``str.join(', ', listx)``).
+
+The :ref:`builtin-filters` below describes all the builtin filters.
+
+.. _tests:
+
+Tests
+-----
+
+Beside filters, there are also so-called "tests" available. Tests can be used
+to test a variable against a common expression. To test a variable or
+expression, you add `is` plus the name of the test after the variable. For
+example, to find out if a variable is defined, you can do ``name is defined``,
+which will then return true or false depending on whether `name` is defined
+in the current template context.
+
+Tests can accept arguments, too. If the test only takes one argument, you can
+leave out the parentheses. For example, the following two
+expressions do the same thing::
+
+ {% if loop.index is divisibleby 3 %}
+ {% if loop.index is divisibleby(3) %}
+
+The :ref:`builtin-tests` below describes all the builtin tests.
+
+
+.. _comments:
+
+Comments
+--------
+
+To comment-out part of a line in a template, use the comment syntax which is
+by default set to ``{# ... #}``. This is useful to comment out parts of the
+template for debugging or to add information for other template designers or
+yourself::
+
+ {# note: commented-out template because we no longer use this
+ {% for user in users %}
+ ...
+ {% endfor %}
+ #}
+
+
+Whitespace Control
+------------------
+
+In the default configuration:
+
+* a single trailing newline is stripped if present
+* other whitespace (spaces, tabs, newlines etc.) is returned unchanged
+
+If an application configures Jinja to `trim_blocks`, the first newline after a
+template tag is removed automatically (like in PHP). The `lstrip_blocks`
+option can also be set to strip tabs and spaces from the beginning of a
+line to the start of a block. (Nothing will be stripped if there are
+other characters before the start of the block.)
+
+With both `trim_blocks` and `lstrip_blocks` enabled, you can put block tags
+on their own lines, and the entire block line will be removed when
+rendered, preserving the whitespace of the contents. For example,
+without the `trim_blocks` and `lstrip_blocks` options, this template::
+
+ <div>
+ {% if True %}
+ yay
+ {% endif %}
+ </div>
+
+gets rendered with blank lines inside the div::
+
+ <div>
+
+ yay
+
+ </div>
+
+But with both `trim_blocks` and `lstrip_blocks` enabled, the template block
+lines are removed and other whitespace is preserved::
+
+ <div>
+ yay
+ </div>
+
+You can manually disable the `lstrip_blocks` behavior by putting a
+plus sign (``+``) at the start of a block::
+
+ <div>
+ {%+ if something %}yay{% endif %}
+ </div>
+
+You can also strip whitespace in templates by hand. If you add a minus
+sign (``-``) to the start or end of a block (e.g. a :ref:`for-loop` tag), a
+comment, or a variable expression, the whitespaces before or after
+that block will be removed::
+
+ {% for item in seq -%}
+ {{ item }}
+ {%- endfor %}
+
+This will yield all elements without whitespace between them. If `seq` was
+a list of numbers from ``1`` to ``9``, the output would be ``123456789``.
+
+If :ref:`line-statements` are enabled, they strip leading whitespace
+automatically up to the beginning of the line.
+
+By default, Jinja2 also removes trailing newlines. To keep single
+trailing newlines, configure Jinja to `keep_trailing_newline`.
+
+.. admonition:: Note
+
+ You must not add whitespace between the tag and the minus sign.
+
+ **valid**::
+
+ {%- if foo -%}...{% endif %}
+
+ **invalid**::
+
+ {% - if foo - %}...{% endif %}
+
+
+Escaping
+--------
+
+It is sometimes desirable -- even necessary -- to have Jinja ignore parts
+it would otherwise handle as variables or blocks. For example, if, with
+the default syntax, you want to use ``{{`` as a raw string in a template and
+not start a variable, you have to use a trick.
+
+The easiest way to output a literal variable delimiter (``{{``) is by using a
+variable expression::
+
+ {{ '{{' }}
+
+For bigger sections, it makes sense to mark a block `raw`. For example, to
+include example Jinja syntax in a template, you can use this snippet::
+
+ {% raw %}
+ <ul>
+ {% for item in seq %}
+ <li>{{ item }}</li>
+ {% endfor %}
+ </ul>
+ {% endraw %}
+
+
+.. _line-statements:
+
+Line Statements
+---------------
+
+If line statements are enabled by the application, it's possible to mark a
+line as a statement. For example, if the line statement prefix is configured
+to ``#``, the following two examples are equivalent::
+
+ <ul>
+ # for item in seq
+ <li>{{ item }}</li>
+ # endfor
+ </ul>
+
+ <ul>
+ {% for item in seq %}
+ <li>{{ item }}</li>
+ {% endfor %}
+ </ul>
+
+The line statement prefix can appear anywhere on the line as long as no text
+precedes it. For better readability, statements that start a block (such as
+`for`, `if`, `elif` etc.) may end with a colon::
+
+ # for item in seq:
+ ...
+ # endfor
+
+
+.. admonition:: Note
+
+ Line statements can span multiple lines if there are open parentheses,
+ braces or brackets::
+
+ <ul>
+ # for href, caption in [('index.html', 'Index'),
+ ('about.html', 'About')]:
+ <li><a href="{{ href }}">{{ caption }}</a></li>
+ # endfor
+ </ul>
+
+Since Jinja 2.2, line-based comments are available as well. For example, if
+the line-comment prefix is configured to be ``##``, everything from ``##`` to
+the end of the line is ignored (excluding the newline sign)::
+
+ # for item in seq:
+ <li>{{ item }}</li> ## this comment is ignored
+ # endfor
+
+
+.. _template-inheritance:
+
+Template Inheritance
+--------------------
+
+The most powerful part of Jinja is template inheritance. Template inheritance
+allows you to build a base "skeleton" template that contains all the common
+elements of your site and defines **blocks** that child templates can override.
+
+Sounds complicated but is very basic. It's easiest to understand it by starting
+with an example.
+
+
+Base Template
+~~~~~~~~~~~~~
+
+This template, which we'll call ``base.html``, defines a simple HTML skeleton
+document that you might use for a simple two-column page. It's the job of
+"child" templates to fill the empty blocks with content::
+
+ <!DOCTYPE html>
+ <html lang="en">
+ <head>
+ {% block head %}
+ <link rel="stylesheet" href="style.css" />
+ <title>{% block title %}{% endblock %} - My Webpage</title>
+ {% endblock %}
+ </head>
+ <body>
+ <div id="content">{% block content %}{% endblock %}</div>
+ <div id="footer">
+ {% block footer %}
+ &copy; Copyright 2008 by <a href="http://domain.invalid/">you</a>.
+ {% endblock %}
+ </div>
+ </body>
+ </html>
+
+In this example, the ``{% block %}`` tags define four blocks that child templates
+can fill in. All the `block` tag does is tell the template engine that a
+child template may override those placeholders in the template.
+
+Child Template
+~~~~~~~~~~~~~~
+
+A child template might look like this::
+
+ {% extends "base.html" %}
+ {% block title %}Index{% endblock %}
+ {% block head %}
+ {{ super() }}
+ <style type="text/css">
+ .important { color: #336699; }
+ </style>
+ {% endblock %}
+ {% block content %}
+ <h1>Index</h1>
+ <p class="important">
+ Welcome to my awesome homepage.
+ </p>
+ {% endblock %}
+
+The ``{% extends %}`` tag is the key here. It tells the template engine that
+this template "extends" another template. When the template system evaluates
+this template, it first locates the parent. The extends tag should be the
+first tag in the template. Everything before it is printed out normally and
+may cause confusion. For details about this behavior and how to take
+advantage of it, see :ref:`null-master-fallback`.
+
+The filename of the template depends on the template loader. For example, the
+:class:`FileSystemLoader` allows you to access other templates by giving the
+filename. You can access templates in subdirectories with a slash::
+
+ {% extends "layout/default.html" %}
+
+But this behavior can depend on the application embedding Jinja. Note that
+since the child template doesn't define the ``footer`` block, the value from
+the parent template is used instead.
+
+You can't define multiple ``{% block %}`` tags with the same name in the
+same template. This limitation exists because a block tag works in "both"
+directions. That is, a block tag doesn't just provide a placeholder to fill
+- it also defines the content that fills the placeholder in the *parent*.
+If there were two similarly-named ``{% block %}`` tags in a template,
+that template's parent wouldn't know which one of the blocks' content to use.
+
+If you want to print a block multiple times, you can, however, use the special
+`self` variable and call the block with that name::
+
+ <title>{% block title %}{% endblock %}</title>
+ <h1>{{ self.title() }}</h1>
+ {% block body %}{% endblock %}
+
+
+Super Blocks
+~~~~~~~~~~~~
+
+It's possible to render the contents of the parent block by calling `super`.
+This gives back the results of the parent block::
+
+ {% block sidebar %}
+ <h3>Table Of Contents</h3>
+ ...
+ {{ super() }}
+ {% endblock %}
+
+
+Named Block End-Tags
+~~~~~~~~~~~~~~~~~~~~
+
+Jinja2 allows you to put the name of the block after the end tag for better
+readability::
+
+ {% block sidebar %}
+ {% block inner_sidebar %}
+ ...
+ {% endblock inner_sidebar %}
+ {% endblock sidebar %}
+
+However, the name after the `endblock` word must match the block name.
+
+
+Block Nesting and Scope
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Blocks can be nested for more complex layouts. However, per default blocks
+may not access variables from outer scopes::
+
+ {% for item in seq %}
+ <li>{% block loop_item %}{{ item }}{% endblock %}</li>
+ {% endfor %}
+
+This example would output empty ``<li>`` items because `item` is unavailable
+inside the block. The reason for this is that if the block is replaced by
+a child template, a variable would appear that was not defined in the block or
+passed to the context.
+
+Starting with Jinja 2.2, you can explicitly specify that variables are
+available in a block by setting the block to "scoped" by adding the `scoped`
+modifier to a block declaration::
+
+ {% for item in seq %}
+ <li>{% block loop_item scoped %}{{ item }}{% endblock %}</li>
+ {% endfor %}
+
+When overriding a block, the `scoped` modifier does not have to be provided.
+
+
+Template Objects
+~~~~~~~~~~~~~~~~
+
+.. versionchanged:: 2.4
+
+If a template object was passed in the template context, you can
+extend from that object as well. Assuming the calling code passes
+a layout template as `layout_template` to the environment, this
+code works::
+
+ {% extends layout_template %}
+
+Previously, the `layout_template` variable had to be a string with
+the layout template's filename for this to work.
+
+
+HTML Escaping
+-------------
+
+When generating HTML from templates, there's always a risk that a variable will
+include characters that affect the resulting HTML. There are two approaches:
+
+a. manually escaping each variable; or
+b. automatically escaping everything by default.
+
+Jinja supports both. What is used depends on the application configuration.
+The default configuration is no automatic escaping; for various reasons:
+
+- Escaping everything except for safe values will also mean that Jinja is
+ escaping variables known to not include HTML (e.g. numbers, booleans)
+ which can be a huge performance hit.
+
+- The information about the safety of a variable is very fragile. It could
+ happen that by coercing safe and unsafe values, the return value is
+ double-escaped HTML.
+
+Working with Manual Escaping
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If manual escaping is enabled, it's **your** responsibility to escape
+variables if needed. What to escape? If you have a variable that *may*
+include any of the following chars (``>``, ``<``, ``&``, or ``"``) you
+**SHOULD** escape it unless the variable contains well-formed and trusted
+HTML. Escaping works by piping the variable through the ``|e`` filter::
+
+ {{ user.username|e }}
+
+Working with Automatic Escaping
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When automatic escaping is enabled, everything is escaped by default except
+for values explicitly marked as safe. Variables and expressions
+can be marked as safe either in:
+
+a. the context dictionary by the application with `MarkupSafe.Markup`, or
+b. the template, with the `|safe` filter
+
+The main problem with this approach is that Python itself doesn't have the
+concept of tainted values; so whether a value is safe or unsafe can get lost.
+
+If a value is not marked safe, auto-escaping will take place; which means that
+you could end up with double-escaped contents. Double-escaping is easy to
+avoid, however: just rely on the tools Jinja2 provides and *don't use builtin
+Python constructs such as str.format or the string modulo operator (%)*.
+
+Jinja2 functions (macros, `super`, `self.BLOCKNAME`) always return template
+data that is marked as safe.
+
+String literals in templates with automatic escaping are considered unsafe
+because native Python strings (``str``, ``unicode``, ``basestring``) are not
+`MarkupSafe.Markup` strings with an ``__html__`` attribute.
+
+.. _list-of-control-structures:
+
+List of Control Structures
+--------------------------
+
+A control structure refers to all those things that control the flow of a
+program - conditionals (i.e. if/elif/else), for-loops, as well as things like
+macros and blocks. With the default syntax, control structures appear inside
+``{% ... %}`` blocks.
+
+.. _for-loop:
+
+For
+~~~
+
+Loop over each item in a sequence. For example, to display a list of users
+provided in a variable called `users`::
+
+ <h1>Members</h1>
+ <ul>
+ {% for user in users %}
+ <li>{{ user.username|e }}</li>
+ {% endfor %}
+ </ul>
+
+As variables in templates retain their object properties, it is possible to
+iterate over containers like `dict`::
+
+ <dl>
+ {% for key, value in my_dict.iteritems() %}
+ <dt>{{ key|e }}</dt>
+ <dd>{{ value|e }}</dd>
+ {% endfor %}
+ </dl>
+
+Note, however, that **Python dicts are not ordered**; so you might want to
+either pass a sorted ``list`` of ``tuple`` s -- or a
+``collections.OrderedDict`` -- to the template, or use the `dictsort` filter.
+
+Inside of a for-loop block, you can access some special variables:
+
++-----------------------+---------------------------------------------------+
+| Variable | Description |
++=======================+===================================================+
+| `loop.index` | The current iteration of the loop. (1 indexed) |
++-----------------------+---------------------------------------------------+
+| `loop.index0` | The current iteration of the loop. (0 indexed) |
++-----------------------+---------------------------------------------------+
+| `loop.revindex` | The number of iterations from the end of the loop |
+| | (1 indexed) |
++-----------------------+---------------------------------------------------+
+| `loop.revindex0` | The number of iterations from the end of the loop |
+| | (0 indexed) |
++-----------------------+---------------------------------------------------+
+| `loop.first` | True if first iteration. |
++-----------------------+---------------------------------------------------+
+| `loop.last` | True if last iteration. |
++-----------------------+---------------------------------------------------+
+| `loop.length` | The number of items in the sequence. |
++-----------------------+---------------------------------------------------+
+| `loop.cycle` | A helper function to cycle between a list of |
+| | sequences. See the explanation below. |
++-----------------------+---------------------------------------------------+
+| `loop.depth` | Indicates how deep in deep in a recursive loop |
+| | the rendering currently is. Starts at level 1 |
++-----------------------+---------------------------------------------------+
+| `loop.depth0` | Indicates how deep in deep in a recursive loop |
+| | the rendering currently is. Starts at level 0 |
++-----------------------+---------------------------------------------------+
+
+Within a for-loop, it's possible to cycle among a list of strings/variables
+each time through the loop by using the special `loop.cycle` helper::
+
+ {% for row in rows %}
+ <li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
+ {% endfor %}
+
+Since Jinja 2.1, an extra `cycle` helper exists that allows loop-unbound
+cycling. For more information, have a look at the :ref:`builtin-globals`.
+
+.. _loop-filtering:
+
+Unlike in Python, it's not possible to `break` or `continue` in a loop. You
+can, however, filter the sequence during iteration, which allows you to skip
+items. The following example skips all the users which are hidden::
+
+ {% for user in users if not user.hidden %}
+ <li>{{ user.username|e }}</li>
+ {% endfor %}
+
+The advantage is that the special `loop` variable will count correctly; thus
+not counting the users not iterated over.
+
+If no iteration took place because the sequence was empty or the filtering
+removed all the items from the sequence, you can render a default block
+by using `else`::
+
+ <ul>
+ {% for user in users %}
+ <li>{{ user.username|e }}</li>
+ {% else %}
+ <li><em>no users found</em></li>
+ {% endfor %}
+ </ul>
+
+Note that, in Python, `else` blocks are executed whenever the corresponding
+loop **did not** `break`. Since Jinja loops cannot `break` anyway,
+a slightly different behavior of the `else` keyword was chosen.
+
+It is also possible to use loops recursively. This is useful if you are
+dealing with recursive data such as sitemaps or RDFa.
+To use loops recursively, you basically have to add the `recursive` modifier
+to the loop definition and call the `loop` variable with the new iterable
+where you want to recurse.
+
+The following example implements a sitemap with recursive loops::
+
+ <ul class="sitemap">
+ {%- for item in sitemap recursive %}
+ <li><a href="{{ item.href|e }}">{{ item.title }}</a>
+ {%- if item.children -%}
+ <ul class="submenu">{{ loop(item.children) }}</ul>
+ {%- endif %}</li>
+ {%- endfor %}
+ </ul>
+
+The `loop` variable always refers to the closest (innermost) loop. If we
+have more than one level of loops, we can rebind the variable `loop` by
+writing `{% set outer_loop = loop %}` after the loop that we want to
+use recursively. Then, we can call it using `{{ outer_loop(...) }}`
+
+.. _if:
+
+If
+~~
+
+The `if` statement in Jinja is comparable with the Python if statement.
+In the simplest form, you can use it to test if a variable is defined, not
+empty or not false::
+
+ {% if users %}
+ <ul>
+ {% for user in users %}
+ <li>{{ user.username|e }}</li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+
+For multiple branches, `elif` and `else` can be used like in Python. You can
+use more complex :ref:`expressions` there, too::
+
+ {% if kenny.sick %}
+ Kenny is sick.
+ {% elif kenny.dead %}
+ You killed Kenny! You bastard!!!
+ {% else %}
+ Kenny looks okay --- so far
+ {% endif %}
+
+If can also be used as an :ref:`inline expression <if-expression>` and for
+:ref:`loop filtering <loop-filtering>`.
+
+.. _macros:
+
+Macros
+~~~~~~
+
+Macros are comparable with functions in regular programming languages. They
+are useful to put often used idioms into reusable functions to not repeat
+yourself ("DRY").
+
+Here's a small example of a macro that renders a form element::
+
+ {% macro input(name, value='', type='text', size=20) -%}
+ <input type="{{ type }}" name="{{ name }}" value="{{
+ value|e }}" size="{{ size }}">
+ {%- endmacro %}
+
+The macro can then be called like a function in the namespace::
+
+ <p>{{ input('username') }}</p>
+ <p>{{ input('password', type='password') }}</p>
+
+If the macro was defined in a different template, you have to
+:ref:`import <import>` it first.
+
+Inside macros, you have access to three special variables:
+
+`varargs`
+ If more positional arguments are passed to the macro than accepted by the
+ macro, they end up in the special `varargs` variable as a list of values.
+
+`kwargs`
+ Like `varargs` but for keyword arguments. All unconsumed keyword
+ arguments are stored in this special variable.
+
+`caller`
+ If the macro was called from a :ref:`call<call>` tag, the caller is stored
+ in this variable as a callable macro.
+
+Macros also expose some of their internal details. The following attributes
+are available on a macro object:
+
+`name`
+ The name of the macro. ``{{ input.name }}`` will print ``input``.
+
+`arguments`
+ A tuple of the names of arguments the macro accepts.
+
+`defaults`
+ A tuple of default values.
+
+`catch_kwargs`
+ This is `true` if the macro accepts extra keyword arguments (i.e.: accesses
+ the special `kwargs` variable).
+
+`catch_varargs`
+ This is `true` if the macro accepts extra positional arguments (i.e.:
+ accesses the special `varargs` variable).
+
+`caller`
+ This is `true` if the macro accesses the special `caller` variable and may
+ be called from a :ref:`call<call>` tag.
+
+If a macro name starts with an underscore, it's not exported and can't
+be imported.
+
+
+.. _call:
+
+Call
+~~~~
+
+In some cases it can be useful to pass a macro to another macro. For this
+purpose, you can use the special `call` block. The following example shows
+a macro that takes advantage of the call functionality and how it can be
+used::
+
+ {% macro render_dialog(title, class='dialog') -%}
+ <div class="{{ class }}">
+ <h2>{{ title }}</h2>
+ <div class="contents">
+ {{ caller() }}
+ </div>
+ </div>
+ {%- endmacro %}
+
+ {% call render_dialog('Hello World') %}
+ This is a simple dialog rendered by using a macro and
+ a call block.
+ {% endcall %}
+
+It's also possible to pass arguments back to the call block. This makes it
+useful as a replacement for loops. Generally speaking, a call block works
+exactly like a macro without a name.
+
+Here's an example of how a call block can be used with arguments::
+
+ {% macro dump_users(users) -%}
+ <ul>
+ {%- for user in users %}
+ <li><p>{{ user.username|e }}</p>{{ caller(user) }}</li>
+ {%- endfor %}
+ </ul>
+ {%- endmacro %}
+
+ {% call(user) dump_users(list_of_user) %}
+ <dl>
+ <dl>Realname</dl>
+ <dd>{{ user.realname|e }}</dd>
+ <dl>Description</dl>
+ <dd>{{ user.description }}</dd>
+ </dl>
+ {% endcall %}
+
+
+Filters
+~~~~~~~
+
+Filter sections allow you to apply regular Jinja2 filters on a block of
+template data. Just wrap the code in the special `filter` section::
+
+ {% filter upper %}
+ This text becomes uppercase
+ {% endfilter %}
+
+
+.. _assignments:
+
+Assignments
+~~~~~~~~~~~
+
+Inside code blocks, you can also assign values to variables. Assignments at
+top level (outside of blocks, macros or loops) are exported from the template
+like top level macros and can be imported by other templates.
+
+Assignments use the `set` tag and can have multiple targets::
+
+ {% set navigation = [('index.html', 'Index'), ('about.html', 'About')] %}
+ {% set key, value = call_something() %}
+
+
+Block Assignments
+~~~~~~~~~~~~~~~~~
+
+.. versionadded:: 2.8
+
+Starting with Jinja 2.8, it's possible to also use block assignments to
+capture the contents of a block into a variable name. This can be useful
+in some situations as an alternative for macros. In that case, instead of
+using an equals sign and a value, you just write the variable name and then
+everything until ``{% endset %}`` is captured.
+
+Example::
+
+ {% set navigation %}
+ <li><a href="/">Index</a>
+ <li><a href="/downloads">Downloads</a>
+ {% endset %}
+
+The `navigation` variable then contains the navigation HTML source.
+
+
+.. _extends:
+
+Extends
+~~~~~~~
+
+The `extends` tag can be used to extend one template from another. You can
+have multiple `extends` tags in a file, but only one of them may be executed at
+a time.
+
+See the section about :ref:`template-inheritance` above.
+
+
+.. _blocks:
+
+Blocks
+~~~~~~
+
+Blocks are used for inheritance and act as both placeholders and replacements
+at the same time. They are documented in detail in the
+:ref:`template-inheritance` section.
+
+
+Include
+~~~~~~~
+
+The `include` statement is useful to include a template and return the
+rendered contents of that file into the current namespace::
+
+ {% include 'header.html' %}
+ Body
+ {% include 'footer.html' %}
+
+Included templates have access to the variables of the active context by
+default. For more details about context behavior of imports and includes,
+see :ref:`import-visibility`.
+
+From Jinja 2.2 onwards, you can mark an include with ``ignore missing``; in
+which case Jinja will ignore the statement if the template to be included
+does not exist. When combined with ``with`` or ``without context``, it must
+be placed *before* the context visibility statement. Here are some valid
+examples::
+
+ {% include "sidebar.html" ignore missing %}
+ {% include "sidebar.html" ignore missing with context %}
+ {% include "sidebar.html" ignore missing without context %}
+
+.. versionadded:: 2.2
+
+You can also provide a list of templates that are checked for existence
+before inclusion. The first template that exists will be included. If
+`ignore missing` is given, it will fall back to rendering nothing if
+none of the templates exist, otherwise it will raise an exception.
+
+Example::
+
+ {% include ['page_detailed.html', 'page.html'] %}
+ {% include ['special_sidebar.html', 'sidebar.html'] ignore missing %}
+
+.. versionchanged:: 2.4
+ If a template object was passed to the template context, you can
+ include that object using `include`.
+
+.. _import:
+
+Import
+~~~~~~
+
+Jinja2 supports putting often used code into macros. These macros can go into
+different templates and get imported from there. This works similarly to the
+import statements in Python. It's important to know that imports are cached
+and imported templates don't have access to the current template variables,
+just the globals by default. For more details about context behavior of
+imports and includes, see :ref:`import-visibility`.
+
+There are two ways to import templates. You can import a complete template
+into a variable or request specific macros / exported variables from it.
+
+Imagine we have a helper module that renders forms (called `forms.html`)::
+
+ {% macro input(name, value='', type='text') -%}
+ <input type="{{ type }}" value="{{ value|e }}" name="{{ name }}">
+ {%- endmacro %}
+
+ {%- macro textarea(name, value='', rows=10, cols=40) -%}
+ <textarea name="{{ name }}" rows="{{ rows }}" cols="{{ cols
+ }}">{{ value|e }}</textarea>
+ {%- endmacro %}
+
+The easiest and most flexible way to access a template's variables
+and macros is to import the whole template module into a variable.
+That way, you can access the attributes::
+
+ {% import 'forms.html' as forms %}
+ <dl>
+ <dt>Username</dt>
+ <dd>{{ forms.input('username') }}</dd>
+ <dt>Password</dt>
+ <dd>{{ forms.input('password', type='password') }}</dd>
+ </dl>
+ <p>{{ forms.textarea('comment') }}</p>
+
+
+Alternatively, you can import specific names from a template into the current
+namespace::
+
+ {% from 'forms.html' import input as input_field, textarea %}
+ <dl>
+ <dt>Username</dt>
+ <dd>{{ input_field('username') }}</dd>
+ <dt>Password</dt>
+ <dd>{{ input_field('password', type='password') }}</dd>
+ </dl>
+ <p>{{ textarea('comment') }}</p>
+
+Macros and variables starting with one or more underscores are private and
+cannot be imported.
+
+.. versionchanged:: 2.4
+ If a template object was passed to the template context, you can
+ import from that object.
+
+
+.. _import-visibility:
+
+Import Context Behavior
+-----------------------
+
+By default, included templates are passed the current context and imported
+templates are not. The reason for this is that imports, unlike includes,
+are cached; as imports are often used just as a module that holds macros.
+
+This behavior can be changed explicitly: by adding `with context`
+or `without context` to the import/include directive, the current context
+can be passed to the template and caching is disabled automatically.
+
+Here are two examples::
+
+ {% from 'forms.html' import input with context %}
+ {% include 'header.html' without context %}
+
+.. admonition:: Note
+
+ In Jinja 2.0, the context that was passed to the included template
+ did not include variables defined in the template. As a matter of
+ fact, this did not work::
+
+ {% for box in boxes %}
+ {% include "render_box.html" %}
+ {% endfor %}
+
+ The included template ``render_box.html`` is *not* able to access
+ `box` in Jinja 2.0. As of Jinja 2.1, ``render_box.html`` *is* able
+ to do so.
+
+
+.. _expressions:
+
+Expressions
+-----------
+
+Jinja allows basic expressions everywhere. These work very similarly to
+regular Python; even if you're not working with Python
+you should feel comfortable with it.
+
+Literals
+~~~~~~~~
+
+The simplest form of expressions are literals. Literals are representations
+for Python objects such as strings and numbers. The following literals exist:
+
+"Hello World":
+ Everything between two double or single quotes is a string. They are
+ useful whenever you need a string in the template (e.g. as
+ arguments to function calls and filters, or just to extend or include a
+ template).
+
+42 / 42.23:
+ Integers and floating point numbers are created by just writing the
+ number down. If a dot is present, the number is a float, otherwise an
+ integer. Keep in mind that, in Python, ``42`` and ``42.0``
+ are different (``int`` and ``float``, respectively).
+
+['list', 'of', 'objects']:
+ Everything between two brackets is a list. Lists are useful for storing
+ sequential data to be iterated over. For example, you can easily
+ create a list of links using lists and tuples for (and with) a for loop::
+
+ <ul>
+ {% for href, caption in [('index.html', 'Index'), ('about.html', 'About'),
+ ('downloads.html', 'Downloads')] %}
+ <li><a href="{{ href }}">{{ caption }}</a></li>
+ {% endfor %}
+ </ul>
+
+('tuple', 'of', 'values'):
+ Tuples are like lists that cannot be modified ("immutable"). If a tuple
+ only has one item, it must be followed by a comma (``('1-tuple',)``).
+ Tuples are usually used to represent items of two or more elements.
+ See the list example above for more details.
+
+{'dict': 'of', 'key': 'and', 'value': 'pairs'}:
+ A dict in Python is a structure that combines keys and values. Keys must
+ be unique and always have exactly one value. Dicts are rarely used in
+ templates; they are useful in some rare cases such as the :func:`xmlattr`
+ filter.
+
+true / false:
+ true is always true and false is always false.
+
+.. admonition:: Note
+
+ The special constants `true`, `false`, and `none` are indeed lowercase.
+ Because that caused confusion in the past, (`True` used to expand
+ to an undefined variable that was considered false),
+ all three can now also be written in title case
+ (`True`, `False`, and `None`).
+ However, for consistency, (all Jinja identifiers are lowercase)
+ you should use the lowercase versions.
+
+Math
+~~~~
+
+Jinja allows you to calculate with values. This is rarely useful in templates
+but exists for completeness' sake. The following operators are supported:
+
+\+
+ Adds two objects together. Usually the objects are numbers, but if both are
+ strings or lists, you can concatenate them this way. This, however, is not
+ the preferred way to concatenate strings! For string concatenation, have
+ a look-see at the ``~`` operator. ``{{ 1 + 1 }}`` is ``2``.
+
+\-
+ Subtract the second number from the first one. ``{{ 3 - 2 }}`` is ``1``.
+
+/
+ Divide two numbers. The return value will be a floating point number.
+ ``{{ 1 / 2 }}`` is ``{{ 0.5 }}``.
+ (Just like ``from __future__ import division``.)
+
+//
+ Divide two numbers and return the truncated integer result.
+ ``{{ 20 // 7 }}`` is ``2``.
+
+%
+ Calculate the remainder of an integer division. ``{{ 11 % 7 }}`` is ``4``.
+
+\*
+ Multiply the left operand with the right one. ``{{ 2 * 2 }}`` would
+ return ``4``. This can also be used to repeat a string multiple times.
+ ``{{ '=' * 80 }}`` would print a bar of 80 equal signs.
+
+\**
+ Raise the left operand to the power of the right operand. ``{{ 2**3 }}``
+ would return ``8``.
+
+Comparisons
+~~~~~~~~~~~
+
+==
+ Compares two objects for equality.
+
+!=
+ Compares two objects for inequality.
+
+>
+ `true` if the left hand side is greater than the right hand side.
+
+>=
+ `true` if the left hand side is greater or equal to the right hand side.
+
+<
+ `true` if the left hand side is lower than the right hand side.
+
+<=
+ `true` if the left hand side is lower or equal to the right hand side.
+
+Logic
+~~~~~
+
+For `if` statements, `for` filtering, and `if` expressions, it can be useful to
+combine multiple expressions:
+
+and
+ Return true if the left and the right operand are true.
+
+or
+ Return true if the left or the right operand are true.
+
+not
+ negate a statement (see below).
+
+(expr)
+ group an expression.
+
+.. admonition:: Note
+
+ The ``is`` and ``in`` operators support negation using an infix notation,
+ too: ``foo is not bar`` and ``foo not in bar`` instead of ``not foo is bar``
+ and ``not foo in bar``. All other expressions require a prefix notation:
+ ``not (foo and bar).``
+
+
+Other Operators
+~~~~~~~~~~~~~~~
+
+The following operators are very useful but don't fit into any of the other
+two categories:
+
+in
+ Perform a sequence / mapping containment test. Returns true if the left
+ operand is contained in the right. ``{{ 1 in [1, 2, 3] }}`` would, for
+ example, return true.
+
+is
+ Performs a :ref:`test <tests>`.
+
+\|
+ Applies a :ref:`filter <filters>`.
+
+~
+ Converts all operands into strings and concatenates them.
+
+ ``{{ "Hello " ~ name ~ "!" }}`` would return (assuming `name` is set
+ to ``'John'``) ``Hello John!``.
+
+()
+ Call a callable: ``{{ post.render() }}``. Inside of the parentheses you
+ can use positional arguments and keyword arguments like in Python:
+
+ ``{{ post.render(user, full=true) }}``.
+
+. / []
+ Get an attribute of an object. (See :ref:`variables`)
+
+
+.. _if-expression:
+
+If Expression
+~~~~~~~~~~~~~
+
+It is also possible to use inline `if` expressions. These are useful in some
+situations. For example, you can use this to extend from one template if a
+variable is defined, otherwise from the default layout template::
+
+ {% extends layout_template if layout_template is defined else 'master.html' %}
+
+The general syntax is ``<do something> if <something is true> else <do
+something else>``.
+
+The `else` part is optional. If not provided, the else block implicitly
+evaluates into an undefined object::
+
+ {{ '[%s]' % page.title if page.title }}
+
+
+.. _builtin-filters:
+
+List of Builtin Filters
+-----------------------
+
+.. jinjafilters::
+
+
+.. _builtin-tests:
+
+List of Builtin Tests
+---------------------
+
+.. jinjatests::
+
+.. _builtin-globals:
+
+List of Global Functions
+------------------------
+
+The following functions are available in the global scope by default:
+
+.. function:: range([start,] stop[, step])
+
+ Return a list containing an arithmetic progression of integers.
+ ``range(i, j)`` returns ``[i, i+1, i+2, ..., j-1]``;
+ start (!) defaults to ``0``.
+ When step is given, it specifies the increment (or decrement).
+ For example, ``range(4)`` and ``range(0, 4, 1)`` return ``[0, 1, 2, 3]``.
+ The end point is omitted!
+ These are exactly the valid indices for a list of 4 elements.
+
+ This is useful to repeat a template block multiple times, e.g.
+ to fill a list. Imagine you have 7 users in the list but you want to
+ render three empty items to enforce a height with CSS::
+
+ <ul>
+ {% for user in users %}
+ <li>{{ user.username }}</li>
+ {% endfor %}
+ {% for number in range(10 - users|count) %}
+ <li class="empty"><span>...</span></li>
+ {% endfor %}
+ </ul>
+
+.. function:: lipsum(n=5, html=True, min=20, max=100)
+
+ Generates some lorem ipsum for the template. By default, five paragraphs
+ of HTML are generated with each paragraph between 20 and 100 words.
+ If html is False, regular text is returned. This is useful to generate simple
+ contents for layout testing.
+
+.. function:: dict(\**items)
+
+ A convenient alternative to dict literals. ``{'foo': 'bar'}`` is the same
+ as ``dict(foo='bar')``.
+
+.. class:: cycler(\*items)
+
+ The cycler allows you to cycle among values similar to how `loop.cycle`
+ works. Unlike `loop.cycle`, you can use this cycler outside of
+ loops or over multiple loops.
+
+ This can be very useful if you want to show a list of folders and
+ files with the folders on top but both in the same list with alternating
+ row colors.
+
+ The following example shows how `cycler` can be used::
+
+ {% set row_class = cycler('odd', 'even') %}
+ <ul class="browser">
+ {% for folder in folders %}
+ <li class="folder {{ row_class.next() }}">{{ folder|e }}</li>
+ {% endfor %}
+ {% for filename in files %}
+ <li class="file {{ row_class.next() }}">{{ filename|e }}</li>
+ {% endfor %}
+ </ul>
+
+ A cycler has the following attributes and methods:
+
+ .. method:: reset()
+
+ Resets the cycle to the first item.
+
+ .. method:: next()
+
+ Goes one item ahead and returns the then-current item.
+
+ .. attribute:: current
+
+ Returns the current item.
+
+ **new in Jinja 2.1**
+
+.. class:: joiner(sep=', ')
+
+ A tiny helper that can be used to "join" multiple sections. A joiner is
+ passed a string and will return that string every time it's called, except
+ the first time (in which case it returns an empty string). You can
+ use this to join things::
+
+ {% set pipe = joiner("|") %}
+ {% if categories %} {{ pipe() }}
+ Categories: {{ categories|join(", ") }}
+ {% endif %}
+ {% if author %} {{ pipe() }}
+ Author: {{ author() }}
+ {% endif %}
+ {% if can_edit %} {{ pipe() }}
+ <a href="?action=edit">Edit</a>
+ {% endif %}
+
+ **new in Jinja 2.1**
+
+
+Extensions
+----------
+
+The following sections cover the built-in Jinja2 extensions that may be
+enabled by an application. An application could also provide further
+extensions not covered by this documentation; in which case there should
+be a separate document explaining said :ref:`extensions
+<jinja-extensions>`.
+
+.. _i18n-in-templates:
+
+i18n
+~~~~
+
+If the i18n extension is enabled, it's possible to mark parts in the template
+as translatable. To mark a section as translatable, you can use `trans`::
+
+ <p>{% trans %}Hello {{ user }}!{% endtrans %}</p>
+
+To translate a template expression --- say, using template filters, or by just
+accessing an attribute of an object --- you need to bind the expression to a
+name for use within the translation block::
+
+ <p>{% trans user=user.username %}Hello {{ user }}!{% endtrans %}</p>
+
+If you need to bind more than one expression inside a `trans` tag, separate
+the pieces with a comma (``,``)::
+
+ {% trans book_title=book.title, author=author.name %}
+ This is {{ book_title }} by {{ author }}
+ {% endtrans %}
+
+Inside trans tags no statements are allowed, only variable tags are.
+
+To pluralize, specify both the singular and plural forms with the `pluralize`
+tag, which appears between `trans` and `endtrans`::
+
+ {% trans count=list|length %}
+ There is {{ count }} {{ name }} object.
+ {% pluralize %}
+ There are {{ count }} {{ name }} objects.
+ {% endtrans %}
+
+By default, the first variable in a block is used to determine the correct
+singular or plural form. If that doesn't work out, you can specify the name
+which should be used for pluralizing by adding it as parameter to `pluralize`::
+
+ {% trans ..., user_count=users|length %}...
+ {% pluralize user_count %}...{% endtrans %}
+
+It's also possible to translate strings in expressions. For that purpose,
+three functions exist:
+
+- `gettext`: translate a single string
+- `ngettext`: translate a pluralizable string
+- `_`: alias for `gettext`
+
+For example, you can easily print a translated string like this::
+
+ {{ _('Hello World!') }}
+
+To use placeholders, use the `format` filter::
+
+ {{ _('Hello %(user)s!')|format(user=user.username) }}
+
+For multiple placeholders, always use keyword arguments to `format`,
+as other languages may not use the words in the same order.
+
+.. versionchanged:: 2.5
+
+If newstyle gettext calls are activated (:ref:`newstyle-gettext`), using
+placeholders is a lot easier:
+
+.. sourcecode:: html+jinja
+
+ {{ gettext('Hello World!') }}
+ {{ gettext('Hello %(name)s!', name='World') }}
+ {{ ngettext('%(num)d apple', '%(num)d apples', apples|count) }}
+
+Note that the `ngettext` function's format string automatically receives
+the count as a `num` parameter in addition to the regular parameters.
+
+
+Expression Statement
+~~~~~~~~~~~~~~~~~~~~
+
+If the expression-statement extension is loaded, a tag called `do` is available
+that works exactly like the regular variable expression (``{{ ... }}``); except
+it doesn't print anything. This can be used to modify lists::
+
+ {% do navigation.append('a string') %}
+
+
+Loop Controls
+~~~~~~~~~~~~~
+
+If the application enables the :ref:`loopcontrols-extension`, it's possible to
+use `break` and `continue` in loops. When `break` is reached, the loop is
+terminated; if `continue` is reached, the processing is stopped and continues
+with the next iteration.
+
+Here's a loop that skips every second item::
+
+ {% for user in users %}
+ {%- if loop.index is even %}{% continue %}{% endif %}
+ ...
+ {% endfor %}
+
+Likewise, a loop that stops processing after the 10th iteration::
+
+ {% for user in users %}
+ {%- if loop.index >= 10 %}{% break %}{% endif %}
+ {%- endfor %}
+
+Note that ``loop.index`` starts with 1, and ``loop.index0`` starts with 0
+(See: :ref:`for-loop`).
+
+
+With Statement
+~~~~~~~~~~~~~~
+
+.. versionadded:: 2.3
+
+If the application enables the :ref:`with-extension`, it is possible to
+use the `with` keyword in templates. This makes it possible to create
+a new inner scope. Variables set within this scope are not visible
+outside of the scope.
+
+With in a nutshell::
+
+ {% with %}
+ {% set foo = 42 %}
+ {{ foo }} foo is 42 here
+ {% endwith %}
+ foo is not visible here any longer
+
+Because it is common to set variables at the beginning of the scope,
+you can do that within the `with` statement. The following two examples
+are equivalent::
+
+ {% with foo = 42 %}
+ {{ foo }}
+ {% endwith %}
+
+ {% with %}
+ {% set foo = 42 %}
+ {{ foo }}
+ {% endwith %}
+
+.. _autoescape-overrides:
+
+Autoescape Extension
+--------------------
+
+.. versionadded:: 2.4
+
+If the application enables the :ref:`autoescape-extension`, one can
+activate and deactivate the autoescaping from within the templates.
+
+Example::
+
+ {% autoescape true %}
+ Autoescaping is active within this block
+ {% endautoescape %}
+
+ {% autoescape false %}
+ Autoescaping is inactive within this block
+ {% endautoescape %}
+
+After an `endautoescape` the behavior is reverted to what it was before.
diff --git a/deps/v8_inspector/deps/jinja2/docs/tricks.rst b/deps/v8_inspector/deps/jinja2/docs/tricks.rst
new file mode 100644
index 0000000000..4d33e22070
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/docs/tricks.rst
@@ -0,0 +1,100 @@
+Tips and Tricks
+===============
+
+.. highlight:: html+jinja
+
+This part of the documentation shows some tips and tricks for Jinja2
+templates.
+
+
+.. _null-master-fallback:
+
+Null-Master Fallback
+--------------------
+
+Jinja2 supports dynamic inheritance and does not distinguish between parent
+and child template as long as no `extends` tag is visited. While this leads
+to the surprising behavior that everything before the first `extends` tag
+including whitespace is printed out instead of being ignored, it can be used
+for a neat trick.
+
+Usually child templates extend from one template that adds a basic HTML
+skeleton. However it's possible to put the `extends` tag into an `if` tag to
+only extend from the layout template if the `standalone` variable evaluates
+to false which it does per default if it's not defined. Additionally a very
+basic skeleton is added to the file so that if it's indeed rendered with
+`standalone` set to `True` a very basic HTML skeleton is added::
+
+ {% if not standalone %}{% extends 'master.html' %}{% endif -%}
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+ <title>{% block title %}The Page Title{% endblock %}</title>
+ <link rel="stylesheet" href="style.css" type="text/css">
+ {% block body %}
+ <p>This is the page body.</p>
+ {% endblock %}
+
+
+Alternating Rows
+----------------
+
+If you want to have different styles for each row of a table or
+list you can use the `cycle` method on the `loop` object::
+
+ <ul>
+ {% for row in rows %}
+ <li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
+ {% endfor %}
+ </ul>
+
+`cycle` can take an unlimited amount of strings. Each time this
+tag is encountered the next item from the list is rendered.
+
+
+Highlighting Active Menu Items
+------------------------------
+
+Often you want to have a navigation bar with an active navigation
+item. This is really simple to achieve. Because assignments outside
+of `block`\s in child templates are global and executed before the layout
+template is evaluated it's possible to define the active menu item in the
+child template::
+
+ {% extends "layout.html" %}
+ {% set active_page = "index" %}
+
+The layout template can then access `active_page`. Additionally it makes
+sense to define a default for that variable::
+
+ {% set navigation_bar = [
+ ('/', 'index', 'Index'),
+ ('/downloads/', 'downloads', 'Downloads'),
+ ('/about/', 'about', 'About')
+ ] -%}
+ {% set active_page = active_page|default('index') -%}
+ ...
+ <ul id="navigation">
+ {% for href, id, caption in navigation_bar %}
+ <li{% if id == active_page %} class="active"{% endif
+ %}><a href="{{ href|e }}">{{ caption|e }}</a></li>
+ {% endfor %}
+ </ul>
+ ...
+
+.. _accessing-the-parent-loop:
+
+Accessing the parent Loop
+-------------------------
+
+The special `loop` variable always points to the innermost loop. If it's
+desired to have access to an outer loop it's possible to alias it::
+
+ <table>
+ {% for row in table %}
+ <tr>
+ {% set rowloop = loop %}
+ {% for cell in row %}
+ <td id="cell-{{ rowloop.index }}-{{ loop.index }}">{{ cell }}</td>
+ {% endfor %}
+ </tr>
+ {% endfor %}
+ </table>
diff --git a/deps/v8_inspector/deps/jinja2/examples/basic/cycle.py b/deps/v8_inspector/deps/jinja2/examples/basic/cycle.py
new file mode 100644
index 0000000000..73dd6325eb
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/basic/cycle.py
@@ -0,0 +1,13 @@
+from jinja2 import Environment
+
+
+env = Environment(line_statement_prefix="#", variable_start_string="${", variable_end_string="}")
+
+
+print env.from_string("""\
+<ul>
+# for item in range(10)
+ <li class="${loop.cycle('odd', 'even')}">${item}</li>
+# endfor
+</ul>\
+""").render()
diff --git a/deps/v8_inspector/deps/jinja2/examples/basic/debugger.py b/deps/v8_inspector/deps/jinja2/examples/basic/debugger.py
new file mode 100644
index 0000000000..4291ff7ac4
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/basic/debugger.py
@@ -0,0 +1,7 @@
+from jinja2 import Environment
+from jinja2.loaders import FileSystemLoader
+
+env = Environment(loader=FileSystemLoader('templates'))
+
+tmpl = env.get_template('broken.html')
+print tmpl.render(seq=[3, 2, 4, 5, 3, 2, 0, 2, 1])
diff --git a/deps/v8_inspector/deps/jinja2/examples/basic/inheritance.py b/deps/v8_inspector/deps/jinja2/examples/basic/inheritance.py
new file mode 100644
index 0000000000..aa687c898a
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/basic/inheritance.py
@@ -0,0 +1,12 @@
+from jinja2 import Environment
+from jinja2.loaders import DictLoader
+
+
+env = Environment(loader=DictLoader({
+'a': '''[A[{% block body %}{% endblock %}]]''',
+'b': '''{% extends 'a' %}{% block body %}[B]{% endblock %}''',
+'c': '''{% extends 'b' %}{% block body %}###{{ super() }}###{% endblock %}'''
+}))
+
+
+print env.get_template('c').render()
diff --git a/deps/v8_inspector/deps/jinja2/examples/basic/templates/broken.html b/deps/v8_inspector/deps/jinja2/examples/basic/templates/broken.html
new file mode 100644
index 0000000000..294d5c9989
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/basic/templates/broken.html
@@ -0,0 +1,6 @@
+{% from 'subbroken.html' import may_break %}
+<ul>
+{% for item in seq %}
+ <li>{{ may_break(item) }}</li>
+{% endfor %}
+</ul>
diff --git a/deps/v8_inspector/deps/jinja2/examples/basic/templates/subbroken.html b/deps/v8_inspector/deps/jinja2/examples/basic/templates/subbroken.html
new file mode 100644
index 0000000000..245eb7e6e6
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/basic/templates/subbroken.html
@@ -0,0 +1,3 @@
+{% macro may_break(item) -%}
+ [{{ item / 0 }}]
+{%- endmacro %}
diff --git a/deps/v8_inspector/deps/jinja2/examples/basic/test.py b/deps/v8_inspector/deps/jinja2/examples/basic/test.py
new file mode 100644
index 0000000000..8f7dde7922
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/basic/test.py
@@ -0,0 +1,27 @@
+from jinja2 import Environment
+from jinja2.loaders import DictLoader
+
+env = Environment(loader=DictLoader({
+'child.html': u'''\
+{% extends master_layout or 'master.html' %}
+{% include helpers = 'helpers.html' %}
+{% macro get_the_answer() %}42{% endmacro %}
+{% title = 'Hello World' %}
+{% block body %}
+ {{ get_the_answer() }}
+ {{ helpers.conspirate() }}
+{% endblock %}
+''',
+'master.html': u'''\
+<!doctype html>
+<title>{{ title }}</title>
+{% block body %}{% endblock %}
+''',
+'helpers.html': u'''\
+{% macro conspirate() %}23{% endmacro %}
+'''
+}))
+
+
+tmpl = env.get_template("child.html")
+print(tmpl.render())
diff --git a/deps/v8_inspector/deps/jinja2/examples/basic/test_filter_and_linestatements.py b/deps/v8_inspector/deps/jinja2/examples/basic/test_filter_and_linestatements.py
new file mode 100644
index 0000000000..79e0a4b371
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/basic/test_filter_and_linestatements.py
@@ -0,0 +1,25 @@
+from jinja2 import Environment
+
+
+env = Environment(line_statement_prefix='%', variable_start_string="${", variable_end_string="}")
+tmpl = env.from_string("""\
+% macro foo()
+ ${caller(42)}
+% endmacro
+<ul>
+% for item in seq
+ <li>${item}</li>
+% endfor
+</ul>
+% call(var) foo()
+ [${var}]
+% endcall
+% filter escape
+ <hello world>
+ % for item in [1, 2, 3]
+ - ${item}
+ % endfor
+% endfilter
+""")
+
+print(tmpl.render(seq=range(10)))
diff --git a/deps/v8_inspector/deps/jinja2/examples/basic/test_loop_filter.py b/deps/v8_inspector/deps/jinja2/examples/basic/test_loop_filter.py
new file mode 100644
index 0000000000..0469d04e43
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/basic/test_loop_filter.py
@@ -0,0 +1,12 @@
+from jinja2 import Environment
+
+tmpl = Environment().from_string("""\
+<ul>
+{%- for item in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] if item % 2 == 0 %}
+ <li>{{ loop.index }} / {{ loop.length }}: {{ item }}</li>
+{%- endfor %}
+</ul>
+if condition: {{ 1 if foo else 0 }}
+""")
+
+print(tmpl.render(foo=True))
diff --git a/deps/v8_inspector/deps/jinja2/examples/basic/translate.py b/deps/v8_inspector/deps/jinja2/examples/basic/translate.py
new file mode 100644
index 0000000000..1fb8ee63bf
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/basic/translate.py
@@ -0,0 +1,14 @@
+from jinja2 import Environment
+
+env = Environment(extensions=['jinja2.ext.i18n'])
+env.globals['gettext'] = {
+ 'Hello %(user)s!': 'Hallo %(user)s!'
+}.__getitem__
+env.globals['ngettext'] = lambda s, p, n: {
+ '%(count)s user': '%(count)d Benutzer',
+ '%(count)s users': '%(count)d Benutzer'
+}[n == 1 and s or p]
+print env.from_string("""\
+{% trans %}Hello {{ user }}!{% endtrans %}
+{% trans count=users|count %}{{ count }} user{% pluralize %}{{ count }} users{% endtrans %}
+""").render(user="someone", users=[1, 2, 3])
diff --git a/deps/v8_inspector/deps/jinja2/examples/bench.py b/deps/v8_inspector/deps/jinja2/examples/bench.py
new file mode 100644
index 0000000000..c648dc69b0
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/bench.py
@@ -0,0 +1,433 @@
+"""\
+ This benchmark compares some python templating engines with Jinja 2 so
+ that we get a picture of how fast Jinja 2 is for a semi real world
+ template. If a template engine is not installed the test is skipped.\
+"""
+import sys
+import cgi
+from timeit import Timer
+from jinja2 import Environment as JinjaEnvironment
+
+context = {
+ 'page_title': 'mitsuhiko\'s benchmark',
+ 'table': [dict(a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8,i=9,j=10) for x in range(1000)]
+}
+
+jinja_template = JinjaEnvironment(
+ line_statement_prefix='%',
+ variable_start_string="${",
+ variable_end_string="}"
+).from_string("""\
+<!doctype html>
+<html>
+ <head>
+ <title>${page_title|e}</title>
+ </head>
+ <body>
+ <div class="header">
+ <h1>${page_title|e}</h1>
+ </div>
+ <ul class="navigation">
+ % for href, caption in [
+ ('index.html', 'Index'),
+ ('downloads.html', 'Downloads'),
+ ('products.html', 'Products')
+ ]
+ <li><a href="${href|e}">${caption|e}</a></li>
+ % endfor
+ </ul>
+ <div class="table">
+ <table>
+ % for row in table
+ <tr>
+ % for cell in row
+ <td>${cell}</td>
+ % endfor
+ </tr>
+ % endfor
+ </table>
+ </div>
+ </body>
+</html>\
+""")
+
+def test_jinja():
+ jinja_template.render(context)
+
+try:
+ from tornado.template import Template
+except ImportError:
+ test_tornado = None
+else:
+ tornado_template = Template("""\
+<!doctype html>
+<html>
+ <head>
+ <title>{{ page_title }}</title>
+ </head>
+ <body>
+ <div class="header">
+ <h1>{{ page_title }}</h1>
+ </div>
+ <ul class="navigation">
+ {% for href, caption in [ \
+ ('index.html', 'Index'), \
+ ('downloads.html', 'Downloads'), \
+ ('products.html', 'Products') \
+ ] %}
+ <li><a href="{{ href }}">{{ caption }}</a></li>
+ {% end %}
+ </ul>
+ <div class="table">
+ <table>
+ {% for row in table %}
+ <tr>
+ {% for cell in row %}
+ <td>{{ cell }}</td>
+ {% end %}
+ </tr>
+ {% end %}
+ </table>
+ </div>
+ </body>
+</html>\
+""")
+
+ def test_tornado():
+ tornado_template.generate(**context)
+
+try:
+ from django.conf import settings
+ settings.configure()
+ from django.template import Template as DjangoTemplate, Context as DjangoContext
+except ImportError:
+ test_django = None
+else:
+ django_template = DjangoTemplate("""\
+<!doctype html>
+<html>
+ <head>
+ <title>{{ page_title }}</title>
+ </head>
+ <body>
+ <div class="header">
+ <h1>{{ page_title }}</h1>
+ </div>
+ <ul class="navigation">
+ {% for href, caption in navigation %}
+ <li><a href="{{ href }}">{{ caption }}</a></li>
+ {% endfor %}
+ </ul>
+ <div class="table">
+ <table>
+ {% for row in table %}
+ <tr>
+ {% for cell in row %}
+ <td>{{ cell }}</td>
+ {% endfor %}
+ </tr>
+ {% endfor %}
+ </table>
+ </div>
+ </body>
+</html>\
+""")
+
+ def test_django():
+ c = DjangoContext(context)
+ c['navigation'] = [('index.html', 'Index'), ('downloads.html', 'Downloads'),
+ ('products.html', 'Products')]
+ django_template.render(c)
+
+try:
+ from mako.template import Template as MakoTemplate
+except ImportError:
+ test_mako = None
+else:
+ mako_template = MakoTemplate("""\
+<!doctype html>
+<html>
+ <head>
+ <title>${page_title|h}</title>
+ </head>
+ <body>
+ <div class="header">
+ <h1>${page_title|h}</h1>
+ </div>
+ <ul class="navigation">
+ % for href, caption in [('index.html', 'Index'), ('downloads.html', 'Downloads'), ('products.html', 'Products')]:
+ <li><a href="${href|h}">${caption|h}</a></li>
+ % endfor
+ </ul>
+ <div class="table">
+ <table>
+ % for row in table:
+ <tr>
+ % for cell in row:
+ <td>${cell}</td>
+ % endfor
+ </tr>
+ % endfor
+ </table>
+ </div>
+ </body>
+</html>\
+""")
+
+ def test_mako():
+ mako_template.render(**context)
+
+try:
+ from genshi.template import MarkupTemplate as GenshiTemplate
+except ImportError:
+ test_genshi = None
+else:
+ genshi_template = GenshiTemplate("""\
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://genshi.edgewall.org/">
+ <head>
+ <title>${page_title}</title>
+ </head>
+ <body>
+ <div class="header">
+ <h1>${page_title}</h1>
+ </div>
+ <ul class="navigation">
+ <li py:for="href, caption in [
+ ('index.html', 'Index'),
+ ('downloads.html', 'Downloads'),
+ ('products.html', 'Products')]"><a href="${href}">${caption}</a></li>
+ </ul>
+ <div class="table">
+ <table>
+ <tr py:for="row in table">
+ <td py:for="cell in row">${cell}</td>
+ </tr>
+ </table>
+ </div>
+ </body>
+</html>\
+""")
+
+ def test_genshi():
+ genshi_template.generate(**context).render('html', strip_whitespace=False)
+
+try:
+ from Cheetah.Template import Template as CheetahTemplate
+except ImportError:
+ test_cheetah = None
+else:
+ cheetah_template = CheetahTemplate("""\
+#import cgi
+<!doctype html>
+<html>
+ <head>
+ <title>$cgi.escape($page_title)</title>
+ </head>
+ <body>
+ <div class="header">
+ <h1>$cgi.escape($page_title)</h1>
+ </div>
+ <ul class="navigation">
+ #for $href, $caption in [('index.html', 'Index'), ('downloads.html', 'Downloads'), ('products.html', 'Products')]:
+ <li><a href="$cgi.escape($href)">$cgi.escape($caption)</a></li>
+ #end for
+ </ul>
+ <div class="table">
+ <table>
+ #for $row in $table:
+ <tr>
+ #for $cell in $row:
+ <td>$cell</td>
+ #end for
+ </tr>
+ #end for
+ </table>
+ </div>
+ </body>
+</html>\
+""", searchList=[dict(context)])
+
+ def test_cheetah():
+ unicode(cheetah_template)
+
+try:
+ import tenjin
+except ImportError:
+ test_tenjin = None
+else:
+ tenjin_template = tenjin.Template()
+ tenjin_template.convert("""\
+<!doctype html>
+<html>
+ <head>
+ <title>${page_title}</title>
+ </head>
+ <body>
+ <div class="header">
+ <h1>${page_title}</h1>
+ </div>
+ <ul class="navigation">
+<?py for href, caption in [('index.html', 'Index'), ('downloads.html', 'Downloads'), ('products.html', 'Products')]: ?>
+ <li><a href="${href}">${caption}</a></li>
+<?py #end ?>
+ </ul>
+ <div class="table">
+ <table>
+<?py for row in table: ?>
+ <tr>
+<?py for cell in row: ?>
+ <td>#{cell}</td>
+<?py #end ?>
+ </tr>
+<?py #end ?>
+ </table>
+ </div>
+ </body>
+</html>\
+""")
+
+ def test_tenjin():
+ from tenjin.helpers import escape, to_str
+ tenjin_template.render(context, locals())
+
+try:
+ from spitfire.compiler import util as SpitfireTemplate
+ from spitfire.compiler.analyzer import o2_options as spitfire_optimizer
+except ImportError:
+ test_spitfire = None
+else:
+ spitfire_template = SpitfireTemplate.load_template("""\
+<!doctype html>
+<html>
+ <head>
+ <title>$cgi.escape($page_title)</title>
+ </head>
+ <body>
+ <div class="header">
+ <h1>$cgi.escape($page_title)</h1>
+ </div>
+ <ul class="navigation">
+ #for $href, $caption in [('index.html', 'Index'), ('downloads.html', 'Downloads'), ('products.html', 'Products')]
+ <li><a href="$cgi.escape($href)">$cgi.escape($caption)</a></li>
+ #end for
+ </ul>
+ <div class="table">
+ <table>
+ #for $row in $table
+ <tr>
+ #for $cell in $row
+ <td>$cell</td>
+ #end for
+ </tr>
+ #end for
+ </table>
+ </div>
+ </body>
+</html>\
+""", 'spitfire_tmpl', spitfire_optimizer, {'enable_filters': False})
+ spitfire_context = dict(context, **{'cgi': cgi})
+
+ def test_spitfire():
+ spitfire_template(search_list=[spitfire_context]).main()
+
+
+try:
+ from chameleon.zpt.template import PageTemplate
+except ImportError:
+ test_chameleon = None
+else:
+ chameleon_template = PageTemplate("""\
+<html xmlns:tal="http://xml.zope.org/namespaces/tal">
+ <head>
+ <title tal:content="page_title">Page Title</title>
+ </head>
+ <body>
+ <div class="header">
+ <h1 tal:content="page_title">Page Title</h1>
+ </div>
+ <ul class="navigation">
+ <li tal:repeat="item sections"><a tal:attributes="href item[0]" tal:content="item[1]">caption</a></li>
+ </ul>
+ <div class="table">
+ <table>
+ <tr tal:repeat="row table">
+ <td tal:repeat="cell row" tal:content="row[cell]">cell</td>
+ </tr>
+ </table>
+ </div>
+ </body>
+</html>\
+""")
+ chameleon_context = dict(context)
+ chameleon_context['sections'] = [
+ ('index.html', 'Index'),
+ ('downloads.html', 'Downloads'),
+ ('products.html', 'Products')
+ ]
+ def test_chameleon():
+ chameleon_template.render(**chameleon_context)
+
+try:
+ from chameleon.zpt.template import PageTemplate
+ from chameleon.genshi import language
+except ImportError:
+ test_chameleon_genshi = None
+else:
+ chameleon_genshi_template = PageTemplate("""\
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://genshi.edgewall.org/">
+ <head>
+ <title>${page_title}</title>
+ </head>
+ <body>
+ <div class="header">
+ <h1>${page_title}</h1>
+ </div>
+ <ul class="navigation">
+ <li py:for="info in sections"><a href="${info[0]}">${info[1]}</a></li>
+ </ul>
+ <div class="table">
+ <table>
+ <tr py:for="row in table">
+ <td py:for="cell in row">${row[cell]}</td>
+ </tr>
+ </table>
+ </div>
+ </body>
+</html>\
+""", parser=language.Parser())
+ chameleon_genshi_context = dict(context)
+ chameleon_genshi_context['sections'] = [
+ ('index.html', 'Index'),
+ ('downloads.html', 'Downloads'),
+ ('products.html', 'Products')
+ ]
+ def test_chameleon_genshi():
+ chameleon_genshi_template.render(**chameleon_genshi_context)
+
+
+sys.stdout.write('\r' + '\n'.join((
+ '=' * 80,
+ 'Template Engine BigTable Benchmark'.center(80),
+ '=' * 80,
+ __doc__,
+ '-' * 80
+)) + '\n')
+
+
+for test in 'jinja', 'mako', 'tornado', 'tenjin', 'spitfire', 'django', 'genshi', 'cheetah', 'chameleon', 'chameleon_genshi':
+ if locals()['test_' + test] is None:
+ sys.stdout.write(' %-20s*not installed*\n' % test)
+ continue
+ t = Timer(setup='from __main__ import test_%s as bench' % test,
+ stmt='bench()')
+ sys.stdout.write(' >> %-20s<running>' % test)
+ sys.stdout.flush()
+ sys.stdout.write('\r %-20s%.4f seconds\n' % (test, t.timeit(number=50) / 50))
+sys.stdout.write('-' * 80 + '\n')
+sys.stdout.write('''\
+ WARNING: The results of this benchmark are useless to compare the
+ performance of template engines and should not be taken seriously in any
+ way. It's testing the performance of simple loops and has no real-world
+ usefulnes. It only used to check if changes on the Jinja code affect
+ performance in a good or bad way and how it roughly compares to others.
+''' + '=' * 80 + '\n')
diff --git a/deps/v8_inspector/deps/jinja2/examples/profile.py b/deps/v8_inspector/deps/jinja2/examples/profile.py
new file mode 100644
index 0000000000..0c907ae3f1
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/profile.py
@@ -0,0 +1,52 @@
+try:
+ from cProfile import Profile
+except ImportError:
+ from profile import Profile
+from pstats import Stats
+from jinja2 import Environment as JinjaEnvironment
+
+context = {
+ 'page_title': 'mitsuhiko\'s benchmark',
+ 'table': [dict(a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8,i=9,j=10) for x in range(1000)]
+}
+
+source = """\
+% macro testmacro(x)
+ <span>${x}</span>
+% endmacro
+<!doctype html>
+<html>
+ <head>
+ <title>${page_title|e}</title>
+ </head>
+ <body>
+ <div class="header">
+ <h1>${page_title|e}</h1>
+ </div>
+ <div class="table">
+ <table>
+ % for row in table
+ <tr>
+ % for cell in row
+ <td>${testmacro(cell)}</td>
+ % endfor
+ </tr>
+ % endfor
+ </table>
+ </div>
+ </body>
+</html>\
+"""
+jinja_template = JinjaEnvironment(
+ line_statement_prefix='%',
+ variable_start_string="${",
+ variable_end_string="}"
+).from_string(source)
+print jinja_template.environment.compile(source, raw=True)
+
+
+p = Profile()
+p.runcall(lambda: jinja_template.render(context))
+stats = Stats(p)
+stats.sort_stats('time', 'calls')
+stats.print_stats()
diff --git a/deps/v8_inspector/deps/jinja2/examples/rwbench/django/_form.html b/deps/v8_inspector/deps/jinja2/examples/rwbench/django/_form.html
new file mode 100644
index 0000000000..9c4f710eac
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/rwbench/django/_form.html
@@ -0,0 +1 @@
+<form action="{{ action }}" method="{{ method }}">{{ body }}</form>
diff --git a/deps/v8_inspector/deps/jinja2/examples/rwbench/django/_input_field.html b/deps/v8_inspector/deps/jinja2/examples/rwbench/django/_input_field.html
new file mode 100644
index 0000000000..290fdbd446
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/rwbench/django/_input_field.html
@@ -0,0 +1 @@
+<input type="{{ type }}" value="{{ value }}" name="{{ name }}">
diff --git a/deps/v8_inspector/deps/jinja2/examples/rwbench/django/_textarea.html b/deps/v8_inspector/deps/jinja2/examples/rwbench/django/_textarea.html
new file mode 100644
index 0000000000..7f10424055
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/rwbench/django/_textarea.html
@@ -0,0 +1 @@
+<textarea name="{{ name }}" rows="{{ rows }}" cols="{{ cols }}">{{ value }}</textarea>
diff --git a/deps/v8_inspector/deps/jinja2/examples/rwbench/django/index.html b/deps/v8_inspector/deps/jinja2/examples/rwbench/django/index.html
new file mode 100644
index 0000000000..6f620bb2c0
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/rwbench/django/index.html
@@ -0,0 +1,29 @@
+{% extends "layout.html" %}
+{% block page_title %}Index Page{% endblock %}
+{% block body %}
+ {% for article in articles %}
+ {% if article.published %}
+ <div class="article">
+ <h2><a href="{{ article.href }}">{{ article.title }}</a></h2>
+ <p class="meta">written by <a href="{{ article.user.href }}">{{ article.user.username }}</a> on {{ article.pub_date|dateformat }}</p>
+ <div class="text">{{ article.body|safe }}</div>
+ </div>
+ {% endif %}
+ {% endfor %}
+ {% form %}
+ <dl>
+ <dt>Name</dt>
+ <dd>{% input_field 'name' %}</dd>
+ <dt>E-Mail</dt>
+ <dd>{% input_field 'email' %}</dd>
+ <dt>URL</dt>
+ <dd>{% input_field 'url' %}</dd>
+ <dt>Comment</dt>
+ <dd>{% textarea 'comment' %}</dd>
+ <dt>Captcha</dt>
+ <dd>{% input_field 'captcha' %}</dd>
+ </dl>
+ {% input_field '' 'submit' 'Submit' %}
+ {% input_field 'cancel' 'submit' 'Cancel' %}
+ {% endform %}
+{% endblock %}
diff --git a/deps/v8_inspector/deps/jinja2/examples/rwbench/django/layout.html b/deps/v8_inspector/deps/jinja2/examples/rwbench/django/layout.html
new file mode 100644
index 0000000000..60039cebad
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/rwbench/django/layout.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>{% block page_title %}{% endblock %} | RealWorld Benchmark</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+</head>
+<body>
+ <div class="contents">
+ <div class="header">
+ <h1>RealWorld Benchmark</h1>
+ <blockquote><p>
+ A less stupid benchmark for Mako and Jinja2 to get an impression how
+ code changes affect runtime performance.
+ </p></blockquote>
+ </div>
+ <ul class="navigation">
+ {% for href, caption in page_navigation %}
+ <li><a href="{{ href }}">{{ caption }}</a></li>
+ {% endfor %}
+ </ul>
+ <div class="body">
+ {% block body %}{% endblock %}
+ </div>
+ <div class="footer">
+ &copy; Copyright 2008 by I don't know who.
+ </div>
+ </div>
+</body>
+</html>
diff --git a/deps/v8_inspector/deps/jinja2/examples/rwbench/djangoext.py b/deps/v8_inspector/deps/jinja2/examples/rwbench/djangoext.py
new file mode 100644
index 0000000000..9e9fa6cf0d
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/rwbench/djangoext.py
@@ -0,0 +1,135 @@
+# -*- coding: utf-8 -*-
+from rwbench import ROOT
+from os.path import join
+from django.conf import settings
+settings.configure(
+ TEMPLATE_DIRS=(join(ROOT, 'django'),),
+ TEMPLATE_LOADERS=(
+ ('django.template.loaders.cached.Loader', (
+ 'django.template.loaders.filesystem.Loader',
+ )),
+ )
+)
+from django.template import loader as django_loader, Context as DjangoContext, \
+ Node, NodeList, Variable, TokenParser
+from django import template as django_template_module
+from django.template import Library
+
+
+# for django extensions. We monkey patch our extensions in so that
+# we don't have to initialize a more complex django setup.
+django_extensions = django_template_module.Library()
+django_template_module.builtins.append(django_extensions)
+
+
+from rwbench import dateformat
+django_extensions.filter(dateformat)
+
+
+def var_or_none(x):
+ if x is not None:
+ return Variable(x)
+
+
+# and more django extensions
+@django_extensions.tag
+def input_field(parser, token):
+ p = TokenParser(token.contents)
+ args = [p.value()]
+ while p.more():
+ args.append(p.value())
+ return InputFieldNode(*args)
+
+
+@django_extensions.tag
+def textarea(parser, token):
+ p = TokenParser(token.contents)
+ args = [p.value()]
+ while p.more():
+ args.append(p.value())
+ return TextareaNode(*args)
+
+
+@django_extensions.tag
+def form(parser, token):
+ p = TokenParser(token.contents)
+ args = []
+ while p.more():
+ args.append(p.value())
+ body = parser.parse(('endform',))
+ parser.delete_first_token()
+ return FormNode(body, *args)
+
+
+class InputFieldNode(Node):
+
+ def __init__(self, name, type=None, value=None):
+ self.name = var_or_none(name)
+ self.type = var_or_none(type)
+ self.value = var_or_none(value)
+
+ def render(self, context):
+ name = self.name.resolve(context)
+ type = 'text'
+ value = ''
+ if self.type is not None:
+ type = self.type.resolve(context)
+ if self.value is not None:
+ value = self.value.resolve(context)
+ tmpl = django_loader.get_template('_input_field.html')
+ return tmpl.render(DjangoContext({
+ 'name': name,
+ 'type': type,
+ 'value': value
+ }))
+
+
+class TextareaNode(Node):
+
+ def __init__(self, name, rows=None, cols=None, value=None):
+ self.name = var_or_none(name)
+ self.rows = var_or_none(rows)
+ self.cols = var_or_none(cols)
+ self.value = var_or_none(value)
+
+ def render(self, context):
+ name = self.name.resolve(context)
+ rows = 10
+ cols = 40
+ value = ''
+ if self.rows is not None:
+ rows = int(self.rows.resolve(context))
+ if self.cols is not None:
+ cols = int(self.cols.resolve(context))
+ if self.value is not None:
+ value = self.value.resolve(context)
+ tmpl = django_loader.get_template('_textarea.html')
+ return tmpl.render(DjangoContext({
+ 'name': name,
+ 'rows': rows,
+ 'cols': cols,
+ 'value': value
+ }))
+
+
+class FormNode(Node):
+
+ def __init__(self, body, action=None, method=None):
+ self.body = body
+ self.action = action
+ self.method = method
+
+ def render(self, context):
+ body = self.body.render(context)
+ action = ''
+ method = 'post'
+ if self.action is not None:
+ action = self.action.resolve(context)
+ if self.method is not None:
+ method = self.method.resolve(context)
+ tmpl = django_loader.get_template('_form.html')
+ return tmpl.render(DjangoContext({
+ 'body': body,
+ 'action': action,
+ 'method': method
+ }))
diff --git a/deps/v8_inspector/deps/jinja2/examples/rwbench/genshi/helpers.html b/deps/v8_inspector/deps/jinja2/examples/rwbench/genshi/helpers.html
new file mode 100644
index 0000000000..ecc6dc4d9c
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/rwbench/genshi/helpers.html
@@ -0,0 +1,12 @@
+<div xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://genshi.edgewall.org/"
+ py:strip="">
+
+ <py:def function="input_field(name='', value='', type='text')">
+ <input type="$type" value="$value" name="$name" />
+ </py:def>
+
+ <py:def function="textarea(name, value='', rows=10, cols=40)">
+ <textarea name="$name" rows="$rows" cols="cols">$value</textarea>
+ </py:def>
+
+</div>
diff --git a/deps/v8_inspector/deps/jinja2/examples/rwbench/genshi/index.html b/deps/v8_inspector/deps/jinja2/examples/rwbench/genshi/index.html
new file mode 100644
index 0000000000..70f697d576
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/rwbench/genshi/index.html
@@ -0,0 +1,41 @@
+<?python
+ from rwbench import dateformat
+?>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xi="http://www.w3.org/2001/XInclude"
+ xmlns:py="http://genshi.edgewall.org/">
+ <xi:include href="layout.html" />
+ <xi:include href="helpers.html" />
+ <head><title>Index Page</title></head>
+ <body>
+ <div class="article" py:for="article in articles">
+ <py:if test="article.published">
+ <h2><a href="${article.href}">${article.title}</a></h2>
+ <p class="meta">written by <a href="${article.user.href}"
+ >${article.user.username}</a> on ${dateformat(article.pub_date)}</p>
+ <div class="text">${Markup(article.body)}</div>
+ </py:if>
+ </div>
+ <!--
+ For a fair and balanced comparison we would have to use a def here
+ that wraps the form data but I don't know what would be the best
+ Genshi equivalent for that. Quite frankly I doubt that this makes
+ sense in Genshi anyways.
+ -->
+ <form action="" method="post">
+ <dl>
+ <dt>Name</dt>
+ <dd>${input_field('name')}</dd>
+ <dt>E-Mail</dt>
+ <dd>${input_field('email')}</dd>
+ <dt>URL</dt>
+ <dd>${input_field('url')}</dd>
+ <dt>Comment</dt>
+ <dd>${textarea('comment')}</dd>
+ <dt>Captcha</dt>
+ <dd>${input_field('captcha')}</dd>
+ </dl>
+ ${input_field(type='submit', value='Submit')}
+ ${input_field(name='cancel', type='submit', value='Cancel')}
+ </form>
+ </body>
+</html>
diff --git a/deps/v8_inspector/deps/jinja2/examples/rwbench/genshi/layout.html b/deps/v8_inspector/deps/jinja2/examples/rwbench/genshi/layout.html
new file mode 100644
index 0000000000..b12aec48d8
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/rwbench/genshi/layout.html
@@ -0,0 +1,30 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://genshi.edgewall.org/" >
+ <py:match path="head" once="true">
+ <head>
+ <title>${select('title/text()')} | RealWorld Benchmark</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ </head>
+ </py:match>
+ <py:match path="body" once="true">
+ <body>
+ <div class="contents">
+ <div class="header">
+ <h1>RealWorld Benchmark</h1>
+ <blockquote><p>
+ A less stupid benchmark for Mako and Jinja2 to get an impression how
+ code changes affect runtime performance.
+ </p></blockquote>
+ </div>
+ <ul class="navigation">
+ <li py:for="href, caption in page_navigation"><a href="$href">$caption</a></li>
+ </ul>
+ <div class="body">
+ ${select('*|text()')}
+ </div>
+ <div class="footer">
+ &copy; Copyright 2008 by I don't know who.
+ </div>
+ </div>
+ </body>
+ </py:match>
+</html>
diff --git a/deps/v8_inspector/deps/jinja2/examples/rwbench/jinja/helpers.html b/deps/v8_inspector/deps/jinja2/examples/rwbench/jinja/helpers.html
new file mode 100644
index 0000000000..89976aa05f
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/rwbench/jinja/helpers.html
@@ -0,0 +1,12 @@
+{% macro input_field(name, value='', type='text') -%}
+ <input type="{{ type }}" value="{{ value|e }}" name="{{ name }}">
+{%- endmacro %}
+
+{% macro textarea(name, value='', rows=10, cols=40) -%}
+ <textarea name="{{ name }}" rows="{{ rows }}" cols="{{ cols }}">{{
+ value|e }}</textarea>
+{%- endmacro %}
+
+{% macro form(action='', method='post') -%}
+ <form action="{{ action|e }}" method="{{ method }}">{{ caller() }}</form>
+{%- endmacro %}
diff --git a/deps/v8_inspector/deps/jinja2/examples/rwbench/jinja/index.html b/deps/v8_inspector/deps/jinja2/examples/rwbench/jinja/index.html
new file mode 100644
index 0000000000..b006d0565e
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/rwbench/jinja/index.html
@@ -0,0 +1,29 @@
+{% extends "layout.html" %}
+{% from "helpers.html" import input_field, textarea, form %}
+{% block page_title %}Index Page{% endblock %}
+{% block body %}
+ {%- for article in articles if article.published %}
+ <div class="article">
+ <h2><a href="{{ article.href|e }}">{{ article.title|e }}</a></h2>
+ <p class="meta">written by <a href="{{ article.user.href|e
+ }}">{{ article.user.username|e }}</a> on {{ article.pub_date|dateformat }}</p>
+ <div class="text">{{ article.body }}</div>
+ </div>
+ {%- endfor %}
+ {%- call form() %}
+ <dl>
+ <dt>Name</dt>
+ <dd>{{ input_field('name') }}</dd>
+ <dt>E-Mail</dt>
+ <dd>{{ input_field('email') }}</dd>
+ <dt>URL</dt>
+ <dd>{{ input_field('url') }}</dd>
+ <dt>Comment</dt>
+ <dd>{{ textarea('comment') }}</dd>
+ <dt>Captcha</dt>
+ <dd>{{ input_field('captcha') }}</dd>
+ </dl>
+ {{ input_field(type='submit', value='Submit') }}
+ {{ input_field('cancel', type='submit', value='Cancel') }}
+ {%- endcall %}
+{% endblock %}
diff --git a/deps/v8_inspector/deps/jinja2/examples/rwbench/jinja/layout.html b/deps/v8_inspector/deps/jinja2/examples/rwbench/jinja/layout.html
new file mode 100644
index 0000000000..755789e248
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/rwbench/jinja/layout.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>{% block page_title %}{% endblock %} | RealWorld Benchmark</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+</head>
+<body>
+ <div class="contents">
+ <div class="header">
+ <h1>RealWorld Benchmark</h1>
+ <blockquote><p>
+ A less stupid benchmark for Mako and Jinja2 to get an impression how
+ code changes affect runtime performance.
+ </p></blockquote>
+ </div>
+ <ul class="navigation">
+ {%- for href, caption in page_navigation %}
+ <li><a href="{{ href|e }}">{{ caption }}</a></li>
+ {%- endfor %}
+ </ul>
+ <div class="body">
+ {% block body %}{% endblock %}
+ </div>
+ <div class="footer">
+ &copy; Copyright 2008 by I don't know who.
+ </div>
+ </div>
+</body>
+</html>
diff --git a/deps/v8_inspector/deps/jinja2/examples/rwbench/mako/helpers.html b/deps/v8_inspector/deps/jinja2/examples/rwbench/mako/helpers.html
new file mode 100644
index 0000000000..a0290ebb2e
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/rwbench/mako/helpers.html
@@ -0,0 +1,11 @@
+<%def name="input_field(name='', value='', type='text')">
+ <input type="${type}" value="${value|h}" name="${name}">
+</%def>
+
+<%def name="textarea(name, value='', rows=10, cols=40)">
+ <textarea name="${name}" rows="${rows}" cols="${cols}">${value|h}</textarea>
+</%def>
+
+<%def name="form(action='', method='post')">
+ <form action="${action|h}" method="${method}">${caller.body()}</form>
+</%def>
diff --git a/deps/v8_inspector/deps/jinja2/examples/rwbench/mako/index.html b/deps/v8_inspector/deps/jinja2/examples/rwbench/mako/index.html
new file mode 100644
index 0000000000..c4c6303246
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/rwbench/mako/index.html
@@ -0,0 +1,31 @@
+<%!
+ from rwbench import dateformat
+%>
+<%inherit file="layout.html" />
+<%namespace file="helpers.html" import="input_field, textarea, form" />
+<%def name="page_title()">Index Page</%def>
+% for article in articles:
+ <% if not article.published: continue %>
+<div class="article">
+ <h2><a href="${article.href|h}">${article.title|h}</a></h2>
+ <p class="meta">written by <a href="${article.user.href|h
+ }">${article.user.username|h}</a> on ${dateformat(article.pub_date)}</p>
+ <div class="text">${article.body}</div>
+</div>
+% endfor
+<%call expr="form()">
+ <dl>
+ <dt>Name</dt>
+ <dd>${input_field('name')}</dd>
+ <dt>E-Mail</dt>
+ <dd>${input_field('email')}</dd>
+ <dt>URL</dt>
+ <dd>${input_field('url')}</dd>
+ <dt>Comment</dt>
+ <dd>${textarea('comment')}</dd>
+ <dt>Captcha</dt>
+ <dd>${input_field('captcha')}</dd>
+ </dl>
+ ${input_field(type='submit', value='Submit')}
+ ${input_field(name='cancel', type='submit', value='Cancel')}
+</%call>
diff --git a/deps/v8_inspector/deps/jinja2/examples/rwbench/mako/layout.html b/deps/v8_inspector/deps/jinja2/examples/rwbench/mako/layout.html
new file mode 100644
index 0000000000..a9c353e1c6
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/rwbench/mako/layout.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>${self.page_title()} | RealWorld Benchmark</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+</head>
+<body>
+ <div class="contents">
+ <div class="header">
+ <h1>RealWorld Benchmark</h1>
+ <blockquote><p>
+ A less stupid benchmark for Mako and Jinja2 to get an impression how
+ code changes affect runtime performance.
+ </p></blockquote>
+ </div>
+ <ul class="navigation">
+ % for href, caption in page_navigation:
+ <li><a href="${href|h}">${caption}</a></li>
+ % endfor
+ </ul>
+ <div class="body">
+ ${self.body()}
+ </div>
+ <div class="footer">
+ &copy; Copyright 2008 by I don't know who.
+ </div>
+ </div>
+</body>
+</html>
+<%def name="page_title()"></%def>
diff --git a/deps/v8_inspector/deps/jinja2/examples/rwbench/rwbench.py b/deps/v8_inspector/deps/jinja2/examples/rwbench/rwbench.py
new file mode 100644
index 0000000000..813dd56cf7
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/examples/rwbench/rwbench.py
@@ -0,0 +1,112 @@
+# -*- coding: utf-8 -*-
+"""
+ RealWorldish Benchmark
+ ~~~~~~~~~~~~~~~~~~~~~~
+
+ A more real-world benchmark of Jinja2. Like the other benchmark in the
+ Jinja2 repository this has no real-world usefulnes (despite the name).
+ Just go away and ignore it. NOW!
+
+ :copyright: (c) 2009 by the Jinja Team.
+ :license: BSD.
+"""
+import sys
+from os.path import join, dirname, abspath
+try:
+ from cProfile import Profile
+except ImportError:
+ from profile import Profile
+from pstats import Stats
+ROOT = abspath(dirname(__file__))
+
+from random import choice, randrange
+from datetime import datetime
+from timeit import Timer
+from jinja2 import Environment, FileSystemLoader
+from jinja2.utils import generate_lorem_ipsum
+from mako.lookup import TemplateLookup
+from genshi.template import TemplateLoader as GenshiTemplateLoader
+
+
+def dateformat(x):
+ return x.strftime('%Y-%m-%d')
+
+
+jinja_env = Environment(loader=FileSystemLoader(join(ROOT, 'jinja')))
+jinja_env.filters['dateformat'] = dateformat
+mako_lookup = TemplateLookup(directories=[join(ROOT, 'mako')])
+genshi_loader = GenshiTemplateLoader([join(ROOT, 'genshi')])
+
+class Article(object):
+
+ def __init__(self, id):
+ self.id = id
+ self.href = '/article/%d' % self.id
+ self.title = generate_lorem_ipsum(1, False, 5, 10)
+ self.user = choice(users)
+ self.body = generate_lorem_ipsum()
+ self.pub_date = datetime.utcfromtimestamp(randrange(10 ** 9, 2 * 10 ** 9))
+ self.published = True
+
+
+class User(object):
+
+ def __init__(self, username):
+ self.href = '/user/%s' % username
+ self.username = username
+
+
+users = map(User, [u'John Doe', u'Jane Doe', u'Peter Somewhat'])
+articles = map(Article, range(20))
+navigation = [
+ ('index', 'Index'),
+ ('about', 'About'),
+ ('foo?bar=1', 'Foo with Bar'),
+ ('foo?bar=2&s=x', 'Foo with X'),
+ ('blah', 'Blub Blah'),
+ ('hehe', 'Haha'),
+] * 5
+
+context = dict(users=users, articles=articles, page_navigation=navigation)
+
+
+jinja_template = jinja_env.get_template('index.html')
+mako_template = mako_lookup.get_template('index.html')
+genshi_template = genshi_loader.load('index.html')
+
+
+def test_jinja():
+ jinja_template.render(context)
+
+def test_mako():
+ mako_template.render_unicode(**context)
+
+
+from djangoext import django_loader, DjangoContext
+def test_django():
+ # not cached because django is not thread safe and does
+ # not cache by itself so it would be unfair to cache it here.
+ django_template = django_loader.get_template('index.html')
+ django_template.render(DjangoContext(context))
+
+
+def test_genshi():
+ genshi_template.generate(**context).render('html', doctype='html')
+
+
+if __name__ == '__main__':
+ sys.stdout.write('Realworldish Benchmark:\n')
+ for test in 'jinja', 'mako', 'django', 'genshi':
+ t = Timer(setup='from __main__ import test_%s as bench' % test,
+ stmt='bench()')
+ sys.stdout.write(' >> %-20s<running>' % test)
+ sys.stdout.flush()
+ sys.stdout.write('\r %-20s%.4f seconds\n' % (test, t.timeit(number=200) / 200))
+
+ if '-p' in sys.argv:
+ print 'Jinja profile'
+ p = Profile()
+ p.runcall(test_jinja)
+ stats = Stats(p)
+ stats.sort_stats('time', 'calls')
+ stats.print_stats()
diff --git a/deps/v8_inspector/deps/jinja2/ext/Vim/jinja.vim b/deps/v8_inspector/deps/jinja2/ext/Vim/jinja.vim
new file mode 100644
index 0000000000..ac72efe796
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/ext/Vim/jinja.vim
@@ -0,0 +1,135 @@
+" Vim syntax file
+" Language: Jinja template
+" Maintainer: Armin Ronacher <armin.ronacher@active-4.com>
+" Last Change: 2008 May 9
+" Version: 1.1
+"
+" Known Bugs:
+" because of odd limitations dicts and the modulo operator
+" appear wrong in the template.
+"
+" Changes:
+"
+" 2008 May 9: Added support for Jinja2 changes (new keyword rules)
+
+" .vimrc variable to disable html highlighting
+if !exists('g:jinja_syntax_html')
+ let g:jinja_syntax_html=1
+endif
+
+" For version 5.x: Clear all syntax items
+" For version 6.x: Quit when a syntax file was already loaded
+if !exists("main_syntax")
+ if version < 600
+ syntax clear
+ elseif exists("b:current_syntax")
+ finish
+endif
+ let main_syntax = 'jinja'
+endif
+
+" Pull in the HTML syntax.
+if g:jinja_syntax_html
+ if version < 600
+ so <sfile>:p:h/html.vim
+ else
+ runtime! syntax/html.vim
+ unlet b:current_syntax
+ endif
+endif
+
+syntax case match
+
+" Jinja template built-in tags and parameters (without filter, macro, is and raw, they
+" have special threatment)
+syn keyword jinjaStatement containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained and if else in not or recursive as import
+
+syn keyword jinjaStatement containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained is filter skipwhite nextgroup=jinjaFilter
+syn keyword jinjaStatement containedin=jinjaTagBlock contained macro skipwhite nextgroup=jinjaFunction
+syn keyword jinjaStatement containedin=jinjaTagBlock contained block skipwhite nextgroup=jinjaBlockName
+
+" Variable Names
+syn match jinjaVariable containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained /[a-zA-Z_][a-zA-Z0-9_]*/
+syn keyword jinjaSpecial containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained false true none False True None loop super caller varargs kwargs
+
+" Filters
+syn match jinjaOperator "|" containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained skipwhite nextgroup=jinjaFilter
+syn match jinjaFilter contained /[a-zA-Z_][a-zA-Z0-9_]*/
+syn match jinjaFunction contained /[a-zA-Z_][a-zA-Z0-9_]*/
+syn match jinjaBlockName contained /[a-zA-Z_][a-zA-Z0-9_]*/
+
+" Jinja template constants
+syn region jinjaString containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained start=/"/ skip=/\(\\\)\@<!\(\(\\\\\)\@>\)*\\"/ end=/"/
+syn region jinjaString containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained start=/'/ skip=/\(\\\)\@<!\(\(\\\\\)\@>\)*\\'/ end=/'/
+syn match jinjaNumber containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained /[0-9]\+\(\.[0-9]\+\)\?/
+
+" Operators
+syn match jinjaOperator containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained /[+\-*\/<>=!,:]/
+syn match jinjaPunctuation containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained /[()\[\]]/
+syn match jinjaOperator containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained /\./ nextgroup=jinjaAttribute
+syn match jinjaAttribute contained /[a-zA-Z_][a-zA-Z0-9_]*/
+
+" Jinja template tag and variable blocks
+syn region jinjaNested matchgroup=jinjaOperator start="(" end=")" transparent display containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained
+syn region jinjaNested matchgroup=jinjaOperator start="\[" end="\]" transparent display containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained
+syn region jinjaNested matchgroup=jinjaOperator start="{" end="}" transparent display containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained
+syn region jinjaTagBlock matchgroup=jinjaTagDelim start=/{%-\?/ end=/-\?%}/ containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaRaw,jinjaString,jinjaNested,jinjaComment
+
+syn region jinjaVarBlock matchgroup=jinjaVarDelim start=/{{-\?/ end=/-\?}}/ containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaRaw,jinjaString,jinjaNested,jinjaComment
+
+" Jinja template 'raw' tag
+syn region jinjaRaw matchgroup=jinjaRawDelim start="{%\s*raw\s*%}" end="{%\s*endraw\s*%}" containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaString,jinjaComment
+
+" Jinja comments
+syn region jinjaComment matchgroup=jinjaCommentDelim start="{#" end="#}" containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaString
+
+" Block start keywords. A bit tricker. We only highlight at the start of a
+" tag block and only if the name is not followed by a comma or equals sign
+" which usually means that we have to deal with an assignment.
+syn match jinjaStatement containedin=jinjaTagBlock contained /\({%-\?\s*\)\@<=\<[a-zA-Z_][a-zA-Z0-9_]*\>\(\s*[,=]\)\@!/
+
+" and context modifiers
+syn match jinjaStatement containedin=jinjaTagBlock contained /\<with\(out\)\?\s\+context\>/
+
+
+" Define the default highlighting.
+" For version 5.7 and earlier: only when not done already
+" For version 5.8 and later: only when an item doesn't have highlighting yet
+if version >= 508 || !exists("did_jinja_syn_inits")
+ if version < 508
+ let did_jinja_syn_inits = 1
+ command -nargs=+ HiLink hi link <args>
+ else
+ command -nargs=+ HiLink hi def link <args>
+ endif
+
+ HiLink jinjaPunctuation jinjaOperator
+ HiLink jinjaAttribute jinjaVariable
+ HiLink jinjaFunction jinjaFilter
+
+ HiLink jinjaTagDelim jinjaTagBlock
+ HiLink jinjaVarDelim jinjaVarBlock
+ HiLink jinjaCommentDelim jinjaComment
+ HiLink jinjaRawDelim jinja
+
+ HiLink jinjaSpecial Special
+ HiLink jinjaOperator Normal
+ HiLink jinjaRaw Normal
+ HiLink jinjaTagBlock PreProc
+ HiLink jinjaVarBlock PreProc
+ HiLink jinjaStatement Statement
+ HiLink jinjaFilter Function
+ HiLink jinjaBlockName Function
+ HiLink jinjaVariable Identifier
+ HiLink jinjaString Constant
+ HiLink jinjaNumber Constant
+ HiLink jinjaComment Comment
+
+ delcommand HiLink
+endif
+
+let b:current_syntax = "jinja"
+
+if main_syntax == 'jinja'
+ unlet main_syntax
+endif
diff --git a/deps/v8_inspector/deps/jinja2/ext/django2jinja/django2jinja.py b/deps/v8_inspector/deps/jinja2/ext/django2jinja/django2jinja.py
new file mode 100644
index 0000000000..824d6a1c36
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/ext/django2jinja/django2jinja.py
@@ -0,0 +1,768 @@
+# -*- coding: utf-8 -*-
+"""
+ Django to Jinja
+ ~~~~~~~~~~~~~~~
+
+ Helper module that can convert django templates into Jinja2 templates.
+
+ This file is not intended to be used as stand alone application but to
+ be used as library. To convert templates you basically create your own
+ writer, add extra conversion logic for your custom template tags,
+ configure your django environment and run the `convert_templates`
+ function.
+
+ Here a simple example::
+
+ # configure django (or use settings.configure)
+ import os
+ os.environ['DJANGO_SETTINGS_MODULE'] = 'yourapplication.settings'
+ from yourapplication.foo.templatetags.bar import MyNode
+
+ from django2jinja import Writer, convert_templates
+
+ def write_my_node(writer, node):
+ writer.start_variable()
+ writer.write('myfunc(')
+ for idx, arg in enumerate(node.args):
+ if idx:
+ writer.write(', ')
+ writer.node(arg)
+ writer.write(')')
+ writer.end_variable()
+
+ writer = Writer()
+ writer.node_handlers[MyNode] = write_my_node
+ convert_templates('/path/to/output/folder', writer=writer)
+
+ Here is an example hos to automatically translate your django
+ variables to jinja2::
+
+ import re
+ # List of tuple (Match pattern, Replace pattern, Exclusion pattern)
+
+ var_re = ((re.compile(r"(u|user)\.is_authenticated"), r"\1.is_authenticated()", None),
+ (re.compile(r"\.non_field_errors"), r".non_field_errors()", None),
+ (re.compile(r"\.label_tag"), r".label_tag()", None),
+ (re.compile(r"\.as_dl"), r".as_dl()", None),
+ (re.compile(r"\.as_table"), r".as_table()", None),
+ (re.compile(r"\.as_widget"), r".as_widget()", None),
+ (re.compile(r"\.as_hidden"), r".as_hidden()", None),
+
+ (re.compile(r"\.get_([0-9_\w]+)_url"), r".get_\1_url()", None),
+ (re.compile(r"\.url"), r".url()", re.compile(r"(form|calendar).url")),
+ (re.compile(r"\.get_([0-9_\w]+)_display"), r".get_\1_display()", None),
+ (re.compile(r"loop\.counter"), r"loop.index", None),
+ (re.compile(r"loop\.revcounter"), r"loop.revindex", None),
+ (re.compile(r"request\.GET\.([0-9_\w]+)"), r"request.GET.get('\1', '')", None),
+ (re.compile(r"request\.get_host"), r"request.get_host()", None),
+
+ (re.compile(r"\.all(?!_)"), r".all()", None),
+ (re.compile(r"\.all\.0"), r".all()[0]", None),
+ (re.compile(r"\.([0-9])($|\s+)"), r"[\1]\2", None),
+ (re.compile(r"\.items"), r".items()", None),
+ )
+ writer = Writer(var_re=var_re)
+
+ For details about the writing process have a look at the module code.
+
+ :copyright: (c) 2009 by the Jinja Team.
+ :license: BSD.
+"""
+import re
+import os
+import sys
+from jinja2.defaults import *
+from django.conf import settings
+from django.template import defaulttags as core_tags, loader, TextNode, \
+ FilterExpression, libraries, Variable, loader_tags, TOKEN_TEXT, \
+ TOKEN_VAR
+from django.template.debug import DebugVariableNode as VariableNode
+from django.templatetags import i18n as i18n_tags
+from StringIO import StringIO
+
+
+_node_handlers = {}
+_resolved_filters = {}
+_newline_re = re.compile(r'(?:\r\n|\r|\n)')
+
+
+# Django stores an itertools object on the cycle node. Not only is this
+# thread unsafe but also a problem for the converter which needs the raw
+# string values passed to the constructor to create a jinja loop.cycle()
+# call from it.
+_old_cycle_init = core_tags.CycleNode.__init__
+def _fixed_cycle_init(self, cyclevars, variable_name=None):
+ self.raw_cycle_vars = map(Variable, cyclevars)
+ _old_cycle_init(self, cyclevars, variable_name)
+core_tags.CycleNode.__init__ = _fixed_cycle_init
+
+
+def node(cls):
+ def proxy(f):
+ _node_handlers[cls] = f
+ return f
+ return proxy
+
+
+def convert_templates(output_dir, extensions=('.html', '.txt'), writer=None,
+ callback=None):
+ """Iterates over all templates in the template dirs configured and
+ translates them and writes the new templates into the output directory.
+ """
+ if writer is None:
+ writer = Writer()
+
+ def filter_templates(files):
+ for filename in files:
+ ifilename = filename.lower()
+ for extension in extensions:
+ if ifilename.endswith(extension):
+ yield filename
+
+ def translate(f, loadname):
+ template = loader.get_template(loadname)
+ original = writer.stream
+ writer.stream = f
+ writer.body(template.nodelist)
+ writer.stream = original
+
+ if callback is None:
+ def callback(template):
+ print template
+
+ for directory in settings.TEMPLATE_DIRS:
+ for dirname, _, files in os.walk(directory):
+ dirname = dirname[len(directory) + 1:]
+ for filename in filter_templates(files):
+ source = os.path.normpath(os.path.join(dirname, filename))
+ target = os.path.join(output_dir, dirname, filename)
+ basetarget = os.path.dirname(target)
+ if not os.path.exists(basetarget):
+ os.makedirs(basetarget)
+ callback(source)
+ f = file(target, 'w')
+ try:
+ translate(f, source)
+ finally:
+ f.close()
+
+
+class Writer(object):
+ """The core writer class."""
+
+ def __init__(self, stream=None, error_stream=None,
+ block_start_string=BLOCK_START_STRING,
+ block_end_string=BLOCK_END_STRING,
+ variable_start_string=VARIABLE_START_STRING,
+ variable_end_string=VARIABLE_END_STRING,
+ comment_start_string=COMMENT_START_STRING,
+ comment_end_string=COMMENT_END_STRING,
+ initial_autoescape=True,
+ use_jinja_autoescape=False,
+ custom_node_handlers=None,
+ var_re=[],
+ env=None):
+ if stream is None:
+ stream = sys.stdout
+ if error_stream is None:
+ error_stream = sys.stderr
+ self.stream = stream
+ self.error_stream = error_stream
+ self.block_start_string = block_start_string
+ self.block_end_string = block_end_string
+ self.variable_start_string = variable_start_string
+ self.variable_end_string = variable_end_string
+ self.comment_start_string = comment_start_string
+ self.comment_end_string = comment_end_string
+ self.autoescape = initial_autoescape
+ self.spaceless = False
+ self.use_jinja_autoescape = use_jinja_autoescape
+ self.node_handlers = dict(_node_handlers,
+ **(custom_node_handlers or {}))
+ self._loop_depth = 0
+ self._filters_warned = set()
+ self.var_re = var_re
+ self.env = env
+
+ def enter_loop(self):
+ """Increments the loop depth so that write functions know if they
+ are in a loop.
+ """
+ self._loop_depth += 1
+
+ def leave_loop(self):
+ """Reverse of enter_loop."""
+ self._loop_depth -= 1
+
+ @property
+ def in_loop(self):
+ """True if we are in a loop."""
+ return self._loop_depth > 0
+
+ def write(self, s):
+ """Writes stuff to the stream."""
+ self.stream.write(s.encode(settings.FILE_CHARSET))
+
+ def print_expr(self, expr):
+ """Open a variable tag, write to the string to the stream and close."""
+ self.start_variable()
+ self.write(expr)
+ self.end_variable()
+
+ def _post_open(self):
+ if self.spaceless:
+ self.write('- ')
+ else:
+ self.write(' ')
+
+ def _pre_close(self):
+ if self.spaceless:
+ self.write(' -')
+ else:
+ self.write(' ')
+
+ def start_variable(self):
+ """Start a variable."""
+ self.write(self.variable_start_string)
+ self._post_open()
+
+ def end_variable(self, always_safe=False):
+ """End a variable."""
+ if not always_safe and self.autoescape and \
+ not self.use_jinja_autoescape:
+ self.write('|e')
+ self._pre_close()
+ self.write(self.variable_end_string)
+
+ def start_block(self):
+ """Starts a block."""
+ self.write(self.block_start_string)
+ self._post_open()
+
+ def end_block(self):
+ """Ends a block."""
+ self._pre_close()
+ self.write(self.block_end_string)
+
+ def tag(self, name):
+ """Like `print_expr` just for blocks."""
+ self.start_block()
+ self.write(name)
+ self.end_block()
+
+ def variable(self, name):
+ """Prints a variable. This performs variable name transformation."""
+ self.write(self.translate_variable_name(name))
+
+ def literal(self, value):
+ """Writes a value as literal."""
+ value = repr(value)
+ if value[:2] in ('u"', "u'"):
+ value = value[1:]
+ self.write(value)
+
+ def filters(self, filters, is_block=False):
+ """Dumps a list of filters."""
+ want_pipe = not is_block
+ for filter, args in filters:
+ name = self.get_filter_name(filter)
+ if name is None:
+ self.warn('Could not find filter %s' % name)
+ continue
+ if name not in DEFAULT_FILTERS and \
+ name not in self._filters_warned:
+ self._filters_warned.add(name)
+ self.warn('Filter %s probably doesn\'t exist in Jinja' %
+ name)
+ if not want_pipe:
+ want_pipe = True
+ else:
+ self.write('|')
+ self.write(name)
+ if args:
+ self.write('(')
+ for idx, (is_var, value) in enumerate(args):
+ if idx:
+ self.write(', ')
+ if is_var:
+ self.node(value)
+ else:
+ self.literal(value)
+ self.write(')')
+
+ def get_location(self, origin, position):
+ """Returns the location for an origin and position tuple as name
+ and lineno.
+ """
+ if hasattr(origin, 'source'):
+ source = origin.source
+ name = '<unknown source>'
+ else:
+ source = origin.loader(origin.loadname, origin.dirs)[0]
+ name = origin.loadname
+ lineno = len(_newline_re.findall(source[:position[0]])) + 1
+ return name, lineno
+
+ def warn(self, message, node=None):
+ """Prints a warning to the error stream."""
+ if node is not None and hasattr(node, 'source'):
+ filename, lineno = self.get_location(*node.source)
+ message = '[%s:%d] %s' % (filename, lineno, message)
+ print >> self.error_stream, message
+
+ def translate_variable_name(self, var):
+ """Performs variable name translation."""
+ if self.in_loop and var == 'forloop' or var.startswith('forloop.'):
+ var = var[3:]
+
+ for reg, rep, unless in self.var_re:
+ no_unless = unless and unless.search(var) or True
+ if reg.search(var) and no_unless:
+ var = reg.sub(rep, var)
+ break
+ return var
+
+ def get_filter_name(self, filter):
+ """Returns the filter name for a filter function or `None` if there
+ is no such filter.
+ """
+ if filter not in _resolved_filters:
+ for library in libraries.values():
+ for key, value in library.filters.iteritems():
+ _resolved_filters[value] = key
+ return _resolved_filters.get(filter, None)
+
+ def node(self, node):
+ """Invokes the node handler for a node."""
+ for cls, handler in self.node_handlers.iteritems():
+ if type(node) is cls or type(node).__name__ == cls:
+ handler(self, node)
+ break
+ else:
+ self.warn('Untranslatable node %s.%s found' % (
+ node.__module__,
+ node.__class__.__name__
+ ), node)
+
+ def body(self, nodes):
+ """Calls node() for every node in the iterable passed."""
+ for node in nodes:
+ self.node(node)
+
+
+@node(TextNode)
+def text_node(writer, node):
+ writer.write(node.s)
+
+
+@node(Variable)
+def variable(writer, node):
+ if node.translate:
+ writer.warn('i18n system used, make sure to install translations', node)
+ writer.write('_(')
+ if node.literal is not None:
+ writer.literal(node.literal)
+ else:
+ writer.variable(node.var)
+ if node.translate:
+ writer.write(')')
+
+
+@node(VariableNode)
+def variable_node(writer, node):
+ writer.start_variable()
+ if node.filter_expression.var.var == 'block.super' \
+ and not node.filter_expression.filters:
+ writer.write('super()')
+ else:
+ writer.node(node.filter_expression)
+ writer.end_variable()
+
+
+@node(FilterExpression)
+def filter_expression(writer, node):
+ writer.node(node.var)
+ writer.filters(node.filters)
+
+
+@node(core_tags.CommentNode)
+def comment_tag(writer, node):
+ pass
+
+
+@node(core_tags.DebugNode)
+def comment_tag(writer, node):
+ writer.warn('Debug tag detected. Make sure to add a global function '
+ 'called debug to the namespace.', node=node)
+ writer.print_expr('debug()')
+
+
+@node(core_tags.ForNode)
+def for_loop(writer, node):
+ writer.start_block()
+ writer.write('for ')
+ for idx, var in enumerate(node.loopvars):
+ if idx:
+ writer.write(', ')
+ writer.variable(var)
+ writer.write(' in ')
+ if node.is_reversed:
+ writer.write('(')
+ writer.node(node.sequence)
+ if node.is_reversed:
+ writer.write(')|reverse')
+ writer.end_block()
+ writer.enter_loop()
+ writer.body(node.nodelist_loop)
+ writer.leave_loop()
+ writer.tag('endfor')
+
+
+@node(core_tags.IfNode)
+def if_condition(writer, node):
+ writer.start_block()
+ writer.write('if ')
+ join_with = 'and'
+ if node.link_type == core_tags.IfNode.LinkTypes.or_:
+ join_with = 'or'
+
+ for idx, (ifnot, expr) in enumerate(node.bool_exprs):
+ if idx:
+ writer.write(' %s ' % join_with)
+ if ifnot:
+ writer.write('not ')
+ writer.node(expr)
+ writer.end_block()
+ writer.body(node.nodelist_true)
+ if node.nodelist_false:
+ writer.tag('else')
+ writer.body(node.nodelist_false)
+ writer.tag('endif')
+
+
+@node(core_tags.IfEqualNode)
+def if_equal(writer, node):
+ writer.start_block()
+ writer.write('if ')
+ writer.node(node.var1)
+ if node.negate:
+ writer.write(' != ')
+ else:
+ writer.write(' == ')
+ writer.node(node.var2)
+ writer.end_block()
+ writer.body(node.nodelist_true)
+ if node.nodelist_false:
+ writer.tag('else')
+ writer.body(node.nodelist_false)
+ writer.tag('endif')
+
+
+@node(loader_tags.BlockNode)
+def block(writer, node):
+ writer.tag('block ' + node.name.replace('-', '_').rstrip('_'))
+ node = node
+ while node.parent is not None:
+ node = node.parent
+ writer.body(node.nodelist)
+ writer.tag('endblock')
+
+
+@node(loader_tags.ExtendsNode)
+def extends(writer, node):
+ writer.start_block()
+ writer.write('extends ')
+ if node.parent_name_expr:
+ writer.node(node.parent_name_expr)
+ else:
+ writer.literal(node.parent_name)
+ writer.end_block()
+ writer.body(node.nodelist)
+
+
+@node(loader_tags.ConstantIncludeNode)
+@node(loader_tags.IncludeNode)
+def include(writer, node):
+ writer.start_block()
+ writer.write('include ')
+ if hasattr(node, 'template'):
+ writer.literal(node.template.name)
+ else:
+ writer.node(node.template_name)
+ writer.end_block()
+
+
+@node(core_tags.CycleNode)
+def cycle(writer, node):
+ if not writer.in_loop:
+ writer.warn('Untranslatable free cycle (cycle outside loop)', node=node)
+ return
+ if node.variable_name is not None:
+ writer.start_block()
+ writer.write('set %s = ' % node.variable_name)
+ else:
+ writer.start_variable()
+ writer.write('loop.cycle(')
+ for idx, var in enumerate(node.raw_cycle_vars):
+ if idx:
+ writer.write(', ')
+ writer.node(var)
+ writer.write(')')
+ if node.variable_name is not None:
+ writer.end_block()
+ else:
+ writer.end_variable()
+
+
+@node(core_tags.FilterNode)
+def filter(writer, node):
+ writer.start_block()
+ writer.write('filter ')
+ writer.filters(node.filter_expr.filters, True)
+ writer.end_block()
+ writer.body(node.nodelist)
+ writer.tag('endfilter')
+
+
+@node(core_tags.AutoEscapeControlNode)
+def autoescape_control(writer, node):
+ original = writer.autoescape
+ writer.autoescape = node.setting
+ writer.body(node.nodelist)
+ writer.autoescape = original
+
+
+@node(core_tags.SpacelessNode)
+def spaceless(writer, node):
+ original = writer.spaceless
+ writer.spaceless = True
+ writer.warn('entering spaceless mode with different semantics', node)
+ # do the initial stripping
+ nodelist = list(node.nodelist)
+ if nodelist:
+ if isinstance(nodelist[0], TextNode):
+ nodelist[0] = TextNode(nodelist[0].s.lstrip())
+ if isinstance(nodelist[-1], TextNode):
+ nodelist[-1] = TextNode(nodelist[-1].s.rstrip())
+ writer.body(nodelist)
+ writer.spaceless = original
+
+
+@node(core_tags.TemplateTagNode)
+def template_tag(writer, node):
+ tag = {
+ 'openblock': writer.block_start_string,
+ 'closeblock': writer.block_end_string,
+ 'openvariable': writer.variable_start_string,
+ 'closevariable': writer.variable_end_string,
+ 'opencomment': writer.comment_start_string,
+ 'closecomment': writer.comment_end_string,
+ 'openbrace': '{',
+ 'closebrace': '}'
+ }.get(node.tagtype)
+ if tag:
+ writer.start_variable()
+ writer.literal(tag)
+ writer.end_variable()
+
+
+@node(core_tags.URLNode)
+def url_tag(writer, node):
+ writer.warn('url node used. make sure to provide a proper url() '
+ 'function', node)
+ if node.asvar:
+ writer.start_block()
+ writer.write('set %s = ' % node.asvar)
+ else:
+ writer.start_variable()
+ autoescape = writer.autoescape
+ writer.write('url(')
+ writer.literal(node.view_name)
+ for arg in node.args:
+ writer.write(', ')
+ writer.node(arg)
+ for key, arg in node.kwargs.items():
+ writer.write(', %s=' % key)
+ writer.node(arg)
+ writer.write(')')
+ if node.asvar:
+ writer.end_block()
+ else:
+ writer.end_variable()
+
+
+@node(core_tags.WidthRatioNode)
+def width_ratio(writer, node):
+ writer.warn('widthratio expanded into formula. You may want to provide '
+ 'a helper function for this calculation', node)
+ writer.start_variable()
+ writer.write('(')
+ writer.node(node.val_expr)
+ writer.write(' / ')
+ writer.node(node.max_expr)
+ writer.write(' * ')
+ writer.write(str(int(node.max_width)))
+ writer.write(')|round|int')
+ writer.end_variable(always_safe=True)
+
+
+@node(core_tags.WithNode)
+def with_block(writer, node):
+ writer.warn('with block expanded into set statement. This could cause '
+ 'variables following that block to be overridden.', node)
+ writer.start_block()
+ writer.write('set %s = ' % node.name)
+ writer.node(node.var)
+ writer.end_block()
+ writer.body(node.nodelist)
+
+
+@node(core_tags.RegroupNode)
+def regroup(writer, node):
+ if node.expression.var.literal:
+ writer.warn('literal in groupby filter used. Behavior in that '
+ 'situation is undefined and translation is skipped.', node)
+ return
+ elif node.expression.filters:
+ writer.warn('filters in groupby filter used. Behavior in that '
+ 'situation is undefined which is most likely a bug '
+ 'in your code. Filters were ignored.', node)
+ writer.start_block()
+ writer.write('set %s = ' % node.var_name)
+ writer.node(node.target)
+ writer.write('|groupby(')
+ writer.literal(node.expression.var.var)
+ writer.write(')')
+ writer.end_block()
+
+
+@node(core_tags.LoadNode)
+def warn_load(writer, node):
+ writer.warn('load statement used which was ignored on conversion', node)
+
+
+@node(i18n_tags.GetAvailableLanguagesNode)
+def get_available_languages(writer, node):
+ writer.warn('make sure to provide a get_available_languages function', node)
+ writer.tag('set %s = get_available_languages()' %
+ writer.translate_variable_name(node.variable))
+
+
+@node(i18n_tags.GetCurrentLanguageNode)
+def get_current_language(writer, node):
+ writer.warn('make sure to provide a get_current_language function', node)
+ writer.tag('set %s = get_current_language()' %
+ writer.translate_variable_name(node.variable))
+
+
+@node(i18n_tags.GetCurrentLanguageBidiNode)
+def get_current_language_bidi(writer, node):
+ writer.warn('make sure to provide a get_current_language_bidi function', node)
+ writer.tag('set %s = get_current_language_bidi()' %
+ writer.translate_variable_name(node.variable))
+
+
+@node(i18n_tags.TranslateNode)
+def simple_gettext(writer, node):
+ writer.warn('i18n system used, make sure to install translations', node)
+ writer.start_variable()
+ writer.write('_(')
+ writer.node(node.value)
+ writer.write(')')
+ writer.end_variable()
+
+
+@node(i18n_tags.BlockTranslateNode)
+def translate_block(writer, node):
+ first_var = []
+ variables = set()
+
+ def touch_var(name):
+ variables.add(name)
+ if not first_var:
+ first_var.append(name)
+
+ def dump_token_list(tokens):
+ for token in tokens:
+ if token.token_type == TOKEN_TEXT:
+ writer.write(token.contents)
+ elif token.token_type == TOKEN_VAR:
+ writer.print_expr(token.contents)
+ touch_var(token.contents)
+
+ writer.warn('i18n system used, make sure to install translations', node)
+ writer.start_block()
+ writer.write('trans')
+ idx = -1
+ for idx, (key, var) in enumerate(node.extra_context.items()):
+ if idx:
+ writer.write(',')
+ writer.write(' %s=' % key)
+ touch_var(key)
+ writer.node(var.filter_expression)
+
+ have_plural = False
+ plural_var = None
+ if node.plural and node.countervar and node.counter:
+ have_plural = True
+ plural_var = node.countervar
+ if plural_var not in variables:
+ if idx > -1:
+ writer.write(',')
+ touch_var(plural_var)
+ writer.write(' %s=' % plural_var)
+ writer.node(node.counter)
+
+ writer.end_block()
+ dump_token_list(node.singular)
+ if node.plural and node.countervar and node.counter:
+ writer.start_block()
+ writer.write('pluralize')
+ if node.countervar != first_var[0]:
+ writer.write(' ' + node.countervar)
+ writer.end_block()
+ dump_token_list(node.plural)
+ writer.tag('endtrans')
+
+@node("SimpleNode")
+def simple_tag(writer, node):
+ """Check if the simple tag exist as a filter in """
+ name = node.tag_name
+ if writer.env and \
+ name not in writer.env.filters and \
+ name not in writer._filters_warned:
+ writer._filters_warned.add(name)
+ writer.warn('Filter %s probably doesn\'t exist in Jinja' %
+ name)
+
+ if not node.vars_to_resolve:
+ # No argument, pass the request
+ writer.start_variable()
+ writer.write('request|')
+ writer.write(name)
+ writer.end_variable()
+ return
+
+ first_var = node.vars_to_resolve[0]
+ args = node.vars_to_resolve[1:]
+ writer.start_variable()
+
+ # Copied from Writer.filters()
+ writer.node(first_var)
+
+ writer.write('|')
+ writer.write(name)
+ if args:
+ writer.write('(')
+ for idx, var in enumerate(args):
+ if idx:
+ writer.write(', ')
+ if var.var:
+ writer.node(var)
+ else:
+ writer.literal(var.literal)
+ writer.write(')')
+ writer.end_variable()
+
+# get rid of node now, it shouldn't be used normally
+del node
diff --git a/deps/v8_inspector/deps/jinja2/ext/django2jinja/example.py b/deps/v8_inspector/deps/jinja2/ext/django2jinja/example.py
new file mode 100644
index 0000000000..2d4ab9add8
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/ext/django2jinja/example.py
@@ -0,0 +1,7 @@
+from django.conf import settings
+settings.configure(TEMPLATE_DIRS=['templates'], TEMPLATE_DEBUG=True)
+
+from django2jinja import convert_templates, Writer
+
+writer = Writer(use_jinja_autoescape=True)
+convert_templates('converted', writer=writer)
diff --git a/deps/v8_inspector/deps/jinja2/ext/django2jinja/templates/index.html b/deps/v8_inspector/deps/jinja2/ext/django2jinja/templates/index.html
new file mode 100644
index 0000000000..d0fbe3854d
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/ext/django2jinja/templates/index.html
@@ -0,0 +1,58 @@
+{% extends "layout.html" %}
+{% load i18n %}
+{% block title %}Foo{% endblock %}
+{% block page-body %}
+ {{ block.super }}
+ Hello {{ name|cut:"d" }}!
+
+ {% for item in seq reversed %}
+ {% if forloop.index|divisibleby:2 %}
+ <li class="{% cycle 'a' 'b' %}">{{ item }}</li>
+ {% endif %}
+ {% endfor %}
+ {% ifequal foo bar %}
+ haha
+ {% else %}
+ hmm
+ {% endifequal %}
+ {% filter upper %}
+ {% include "subtemplate.html" %}
+ {% include foo %}
+ {% endfilter %}
+ {% spaceless %}
+ Hello World
+ {{ foo }}
+ Hmm
+ {% endspaceless %}
+ {% templatetag opencomment %}...{% templatetag closecomment %}
+ {% url foo a, b, c=d %}
+ {% url foo a, b, c=d as hmm %}
+
+ {% with object.value as value %}
+ <img src='bar.gif' height='10' width='{% widthratio value 200 100 %}'>
+ {% endwith %}
+
+ <pre>{% debug %}</pre>
+
+ {% blocktrans with book|title as book_t and author|title as author_t %}
+ This is {{ book_t }} by {{ author_t }}
+ {% endblocktrans %}
+
+ {% blocktrans count list|length as counter %}
+ There is only one {{ name }} object.
+ {% plural %}
+ There are {{ counter }} {{ name }} objects.
+ {% endblocktrans %}
+
+ {% blocktrans with name|escape as name count list|length as counter %}
+ There is only one {{ name }} object.
+ {% plural %}
+ There are {{ counter }} {{ name }} objects.
+ {% endblocktrans %}
+
+ {% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %}
+
+ <p>{% trans "This is the title." %}</p>
+
+ {% regroup people by gender as grouped %}
+{% endblock %}
diff --git a/deps/v8_inspector/deps/jinja2/ext/django2jinja/templates/layout.html b/deps/v8_inspector/deps/jinja2/ext/django2jinja/templates/layout.html
new file mode 100644
index 0000000000..3f21a122df
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/ext/django2jinja/templates/layout.html
@@ -0,0 +1,4 @@
+<title>{% block title %}{% endblock %}</title>
+<div class="body">
+ {% block page-body %}{% endblock %}
+</div>
diff --git a/deps/v8_inspector/deps/jinja2/ext/django2jinja/templates/subtemplate.html b/deps/v8_inspector/deps/jinja2/ext/django2jinja/templates/subtemplate.html
new file mode 100644
index 0000000000..980a0d5f19
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/ext/django2jinja/templates/subtemplate.html
@@ -0,0 +1 @@
+Hello World!
diff --git a/deps/v8_inspector/deps/jinja2/ext/djangojinja2.py b/deps/v8_inspector/deps/jinja2/ext/djangojinja2.py
new file mode 100644
index 0000000000..c7b4884d72
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/ext/djangojinja2.py
@@ -0,0 +1,86 @@
+# -*- coding: utf-8 -*-
+"""
+ djangojinja2
+ ~~~~~~~~~~~~
+
+ Adds support for Jinja2 to Django.
+
+ Configuration variables:
+
+ ======================= =============================================
+ Key Description
+ ======================= =============================================
+ `JINJA2_TEMPLATE_DIRS` List of template folders
+ `JINJA2_EXTENSIONS` List of Jinja2 extensions to use
+ `JINJA2_CACHE_SIZE` The size of the Jinja2 template cache.
+ ======================= =============================================
+
+ :copyright: (c) 2009 by the Jinja Team.
+ :license: BSD.
+"""
+from itertools import chain
+from django.conf import settings
+from django.http import HttpResponse
+from django.core.exceptions import ImproperlyConfigured
+from django.template.context import get_standard_processors
+from django.template import TemplateDoesNotExist
+from jinja2 import Environment, FileSystemLoader, TemplateNotFound
+from jinja2.defaults import DEFAULT_NAMESPACE
+
+
+# the environment is unconfigured until the first template is loaded.
+_jinja_env = None
+
+
+def get_env():
+ """Get the Jinja2 env and initialize it if necessary."""
+ global _jinja_env
+ if _jinja_env is None:
+ _jinja_env = create_env()
+ return _jinja_env
+
+
+def create_env():
+ """Create a new Jinja2 environment."""
+ searchpath = list(settings.JINJA2_TEMPLATE_DIRS)
+ return Environment(loader=FileSystemLoader(searchpath),
+ auto_reload=settings.TEMPLATE_DEBUG,
+ cache_size=getattr(settings, 'JINJA2_CACHE_SIZE', 400),
+ extensions=getattr(settings, 'JINJA2_EXTENSIONS', ()))
+
+
+def get_template(template_name, globals=None):
+ """Load a template."""
+ try:
+ return get_env().get_template(template_name, globals=globals)
+ except TemplateNotFound, e:
+ raise TemplateDoesNotExist(str(e))
+
+
+def select_template(templates, globals=None):
+ """Try to load one of the given templates."""
+ env = get_env()
+ for template in templates:
+ try:
+ return env.get_template(template, globals=globals)
+ except TemplateNotFound:
+ continue
+ raise TemplateDoesNotExist(', '.join(templates))
+
+
+def render_to_string(template_name, context=None, request=None,
+ processors=None):
+ """Render a template into a string."""
+ context = dict(context or {})
+ if request is not None:
+ context['request'] = request
+ for processor in chain(get_standard_processors(), processors or ()):
+ context.update(processor(request))
+ return get_template(template_name).render(context)
+
+
+def render_to_response(template_name, context=None, request=None,
+ processors=None, mimetype=None):
+ """Render a template into a response object."""
+ return HttpResponse(render_to_string(template_name, context, request,
+ processors), mimetype=mimetype)
diff --git a/deps/v8_inspector/deps/jinja2/ext/inlinegettext.py b/deps/v8_inspector/deps/jinja2/ext/inlinegettext.py
new file mode 100644
index 0000000000..cf4ed5e441
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/ext/inlinegettext.py
@@ -0,0 +1,78 @@
+# -*- coding: utf-8 -*-
+"""
+ Inline Gettext
+ ~~~~~~~~~~~~~~
+
+ An example extension for Jinja2 that supports inline gettext calls.
+ Requires the i18n extension to be loaded.
+
+ :copyright: (c) 2009 by the Jinja Team.
+ :license: BSD.
+"""
+import re
+from jinja2.ext import Extension
+from jinja2.lexer import Token, count_newlines
+from jinja2.exceptions import TemplateSyntaxError
+
+
+_outside_re = re.compile(r'\\?(gettext|_)\(')
+_inside_re = re.compile(r'\\?[()]')
+
+
+class InlineGettext(Extension):
+ """This extension implements support for inline gettext blocks::
+
+ <h1>_(Welcome)</h1>
+ <p>_(This is a paragraph)</p>
+
+ Requires the i18n extension to be loaded and configured.
+ """
+
+ def filter_stream(self, stream):
+ paren_stack = 0
+
+ for token in stream:
+ if token.type is not 'data':
+ yield token
+ continue
+
+ pos = 0
+ lineno = token.lineno
+
+ while 1:
+ if not paren_stack:
+ match = _outside_re.search(token.value, pos)
+ else:
+ match = _inside_re.search(token.value, pos)
+ if match is None:
+ break
+ new_pos = match.start()
+ if new_pos > pos:
+ preval = token.value[pos:new_pos]
+ yield Token(lineno, 'data', preval)
+ lineno += count_newlines(preval)
+ gtok = match.group()
+ if gtok[0] == '\\':
+ yield Token(lineno, 'data', gtok[1:])
+ elif not paren_stack:
+ yield Token(lineno, 'block_begin', None)
+ yield Token(lineno, 'name', 'trans')
+ yield Token(lineno, 'block_end', None)
+ paren_stack = 1
+ else:
+ if gtok == '(' or paren_stack > 1:
+ yield Token(lineno, 'data', gtok)
+ paren_stack += gtok == ')' and -1 or 1
+ if not paren_stack:
+ yield Token(lineno, 'block_begin', None)
+ yield Token(lineno, 'name', 'endtrans')
+ yield Token(lineno, 'block_end', None)
+ pos = match.end()
+
+ if pos < len(token.value):
+ yield Token(lineno, 'data', token.value[pos:])
+
+ if paren_stack:
+ raise TemplateSyntaxError('unclosed gettext expression',
+ token.lineno, stream.name,
+ stream.filename)
diff --git a/deps/v8_inspector/deps/jinja2/ext/jinja.el b/deps/v8_inspector/deps/jinja2/ext/jinja.el
new file mode 100644
index 0000000000..4cf0c72e29
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/ext/jinja.el
@@ -0,0 +1,128 @@
+;;; jinja.el --- Jinja mode highlighting
+;;
+;; Author: Georg Brandl
+;; Copyright: (c) 2009 by the Jinja Team
+;; Last modified: 2008-05-22 23:04 by gbr
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;; Mostly ripped off django-mode by Lennart Borgman.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; 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; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+(defconst jinja-font-lock-keywords
+ (list
+; (cons (rx "{% comment %}" (submatch (0+ anything))
+; "{% endcomment %}") (list 1 font-lock-comment-face))
+ '("{# ?\\(.*?\\) ?#}" . (1 font-lock-comment-face))
+ '("{%-?\\|-?%}\\|{{\\|}}" . font-lock-preprocessor-face)
+ '("{#\\|#}" . font-lock-comment-delimiter-face)
+ ;; first word in a block is a command
+ '("{%-?[ \t\n]*\\([a-zA-Z_]+\\)" . (1 font-lock-keyword-face))
+ ;; variables
+ '("\\({{ ?\\)\\([^|]*?\\)\\(|.*?\\)? ?}}" . (1 font-lock-variable-name-face))
+ ;; keywords and builtins
+ (cons (rx word-start
+ (or "in" "as" "recursive" "not" "and" "or" "if" "else"
+ "import" "with" "without" "context")
+ word-end)
+ font-lock-keyword-face)
+ (cons (rx word-start
+ (or "true" "false" "none" "loop" "self" "super")
+ word-end)
+ font-lock-builtin-face)
+ ;; tests
+ '("\\(is\\)[ \t]*\\(not\\)[ \t]*\\([a-zA-Z_]+\\)"
+ (1 font-lock-keyword-face) (2 font-lock-keyword-face)
+ (3 font-lock-function-name-face))
+ ;; builtin filters
+ (cons (rx
+ "|" (* space)
+ (submatch
+ (or "abs" "batch" "capitalize" "capture" "center" "count" "default"
+ "dformat" "dictsort" "e" "escape" "filesizeformat" "first"
+ "float" "format" "getattribute" "getitem" "groupby" "indent"
+ "int" "join" "jsonencode" "last" "length" "lower" "markdown"
+ "pprint" "random" "replace" "reverse" "round" "rst" "slice"
+ "sort" "string" "striptags" "sum" "textile" "title" "trim"
+ "truncate" "upper" "urlencode" "urlize" "wordcount" "wordwrap"
+ "xmlattr")))
+ (list 1 font-lock-builtin-face))
+ )
+ "Minimal highlighting expressions for Jinja mode")
+
+(define-derived-mode jinja-mode nil "Jinja"
+ "Simple Jinja mode for use with `mumamo-mode'.
+This mode only provides syntax highlighting."
+ ;;(set (make-local-variable 'comment-start) "{#")
+ ;;(set (make-local-variable 'comment-end) "#}")
+ (setq font-lock-defaults '(jinja-font-lock-keywords)))
+
+;; mumamo stuff
+(when (require 'mumamo nil t)
+
+ (defun mumamo-chunk-jinja3 (pos max)
+ "Find {# ... #}"
+ (mumamo-quick-chunk-forward pos max "{#" "#}" 'borders 'jinja-mode))
+
+ (defun mumamo-chunk-jinja2 (pos max)
+ "Find {{ ... }}"
+ (mumamo-quick-chunk-forward pos max "{{" "}}" 'borders 'jinja-mode))
+
+ (defun mumamo-chunk-jinja (pos max)
+ "Find {% ... %}"
+ (mumamo-quick-chunk-forward pos max "{%" "%}" 'borders 'jinja-mode))
+
+;;;###autoload
+ (define-mumamo-multi-major-mode jinja-html-mumamo
+ "Turn on multiple major modes for Jinja with main mode `html-mode'.
+This also covers inlined style and javascript."
+ ("Jinja HTML Family" html-mode
+ (mumamo-chunk-jinja
+ mumamo-chunk-jinja2
+ mumamo-chunk-jinja3
+ mumamo-chunk-inlined-style
+ mumamo-chunk-inlined-script
+ mumamo-chunk-style=
+ mumamo-chunk-onjs=
+ )))
+
+;;;###autoload
+ (define-mumamo-multi-major-mode jinja-nxhtml-mumamo
+ "Turn on multiple major modes for Jinja with main mode `nxhtml-mode'.
+This also covers inlined style and javascript."
+ ("Jinja nXhtml Family" nxhtml-mode
+ (mumamo-chunk-jinja
+ mumamo-chunk-jinja2
+ mumamo-chunk-jinja3
+ mumamo-chunk-inlined-style
+ mumamo-chunk-inlined-script
+ mumamo-chunk-style=
+ mumamo-chunk-onjs=
+ )))
+ )
+
+(provide 'jinja)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; jinja.el ends here
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/__init__.py b/deps/v8_inspector/deps/jinja2/jinja2/__init__.py
new file mode 100644
index 0000000000..e68c28562b
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/__init__.py
@@ -0,0 +1,70 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2
+ ~~~~~~
+
+ Jinja2 is a template engine written in pure Python. It provides a
+ Django inspired non-XML syntax but supports inline expressions and
+ an optional sandboxed environment.
+
+ Nutshell
+ --------
+
+ Here a small example of a Jinja2 template::
+
+ {% extends 'base.html' %}
+ {% block title %}Memberlist{% endblock %}
+ {% block content %}
+ <ul>
+ {% for user in users %}
+ <li><a href="{{ user.url }}">{{ user.username }}</a></li>
+ {% endfor %}
+ </ul>
+ {% endblock %}
+
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+__docformat__ = 'restructuredtext en'
+__version__ = '2.9.dev'
+
+# high level interface
+from jinja2.environment import Environment, Template
+
+# loaders
+from jinja2.loaders import BaseLoader, FileSystemLoader, PackageLoader, \
+ DictLoader, FunctionLoader, PrefixLoader, ChoiceLoader, \
+ ModuleLoader
+
+# bytecode caches
+from jinja2.bccache import BytecodeCache, FileSystemBytecodeCache, \
+ MemcachedBytecodeCache
+
+# undefined types
+from jinja2.runtime import Undefined, DebugUndefined, StrictUndefined, \
+ make_logging_undefined
+
+# exceptions
+from jinja2.exceptions import TemplateError, UndefinedError, \
+ TemplateNotFound, TemplatesNotFound, TemplateSyntaxError, \
+ TemplateAssertionError
+
+# decorators and public utilities
+from jinja2.filters import environmentfilter, contextfilter, \
+ evalcontextfilter
+from jinja2.utils import Markup, escape, clear_caches, \
+ environmentfunction, evalcontextfunction, contextfunction, \
+ is_undefined
+
+__all__ = [
+ 'Environment', 'Template', 'BaseLoader', 'FileSystemLoader',
+ 'PackageLoader', 'DictLoader', 'FunctionLoader', 'PrefixLoader',
+ 'ChoiceLoader', 'BytecodeCache', 'FileSystemBytecodeCache',
+ 'MemcachedBytecodeCache', 'Undefined', 'DebugUndefined',
+ 'StrictUndefined', 'TemplateError', 'UndefinedError', 'TemplateNotFound',
+ 'TemplatesNotFound', 'TemplateSyntaxError', 'TemplateAssertionError',
+ 'ModuleLoader', 'environmentfilter', 'contextfilter', 'Markup', 'escape',
+ 'environmentfunction', 'contextfunction', 'clear_caches', 'is_undefined',
+ 'evalcontextfilter', 'evalcontextfunction', 'make_logging_undefined',
+]
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/_compat.py b/deps/v8_inspector/deps/jinja2/jinja2/_compat.py
new file mode 100644
index 0000000000..ebe7433074
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/_compat.py
@@ -0,0 +1,102 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2._compat
+ ~~~~~~~~~~~~~~
+
+ Some py2/py3 compatibility support based on a stripped down
+ version of six so we don't have to depend on a specific version
+ of it.
+
+ :copyright: Copyright 2013 by the Jinja team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+import sys
+
+PY2 = sys.version_info[0] == 2
+PYPY = hasattr(sys, 'pypy_translation_info')
+_identity = lambda x: x
+
+
+if not PY2:
+ unichr = chr
+ range_type = range
+ text_type = str
+ string_types = (str,)
+ integer_types = (int,)
+
+ iterkeys = lambda d: iter(d.keys())
+ itervalues = lambda d: iter(d.values())
+ iteritems = lambda d: iter(d.items())
+
+ import pickle
+ from io import BytesIO, StringIO
+ NativeStringIO = StringIO
+
+ def reraise(tp, value, tb=None):
+ if value.__traceback__ is not tb:
+ raise value.with_traceback(tb)
+ raise value
+
+ ifilter = filter
+ imap = map
+ izip = zip
+ intern = sys.intern
+
+ implements_iterator = _identity
+ implements_to_string = _identity
+ encode_filename = _identity
+ get_next = lambda x: x.__next__
+
+else:
+ unichr = unichr
+ text_type = unicode
+ range_type = xrange
+ string_types = (str, unicode)
+ integer_types = (int, long)
+
+ iterkeys = lambda d: d.iterkeys()
+ itervalues = lambda d: d.itervalues()
+ iteritems = lambda d: d.iteritems()
+
+ import cPickle as pickle
+ from cStringIO import StringIO as BytesIO, StringIO
+ NativeStringIO = BytesIO
+
+ exec('def reraise(tp, value, tb=None):\n raise tp, value, tb')
+
+ from itertools import imap, izip, ifilter
+ intern = intern
+
+ def implements_iterator(cls):
+ cls.next = cls.__next__
+ del cls.__next__
+ return cls
+
+ def implements_to_string(cls):
+ cls.__unicode__ = cls.__str__
+ cls.__str__ = lambda x: x.__unicode__().encode('utf-8')
+ return cls
+
+ get_next = lambda x: x.next
+
+ def encode_filename(filename):
+ if isinstance(filename, unicode):
+ return filename.encode('utf-8')
+ return filename
+
+
+def with_metaclass(meta, *bases):
+ """Create a base class with a metaclass."""
+ # This requires a bit of explanation: the basic idea is to make a
+ # dummy metaclass for one level of class instantiation that replaces
+ # itself with the actual metaclass.
+ class metaclass(type):
+ def __new__(cls, name, this_bases, d):
+ return meta(name, bases, d)
+ return type.__new__(metaclass, 'temporary_class', (), {})
+
+
+try:
+ from urllib.parse import quote_from_bytes as url_quote
+except ImportError:
+ from urllib import quote as url_quote
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/_stringdefs.py b/deps/v8_inspector/deps/jinja2/jinja2/_stringdefs.py
new file mode 100644
index 0000000000..da5830e9f1
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/_stringdefs.py
@@ -0,0 +1,132 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2._stringdefs
+ ~~~~~~~~~~~~~~~~~~
+
+ Strings of all Unicode characters of a certain category.
+ Used for matching in Unicode-aware languages. Run to regenerate.
+
+ Inspired by chartypes_create.py from the MoinMoin project, original
+ implementation from Pygments.
+
+ :copyright: Copyright 2006-2009 by the Jinja team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from jinja2._compat import unichr
+
+Cc = u'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f'
+
+Cf = u'\xad\u0600\u0601\u0602\u0603\u06dd\u070f\u17b4\u17b5\u200b\u200c\u200d\u200e\u200f\u202a\u202b\u202c\u202d\u202e\u2060\u2061\u2062\u2063\u206a\u206b\u206c\u206d\u206e\u206f\ufeff\ufff9\ufffa\ufffb'
+
+Cn = u'\u0242\u0243\u0244\u0245\u0246\u0247\u0248\u0249\u024a\u024b\u024c\u024d\u024e\u024f\u0370\u0371\u0372\u0373\u0376\u0377\u0378\u0379\u037b\u037c\u037d\u037f\u0380\u0381\u0382\u0383\u038b\u038d\u03a2\u03cf\u0487\u04cf\u04fa\u04fb\u04fc\u04fd\u04fe\u04ff\u0510\u0511\u0512\u0513\u0514\u0515\u0516\u0517\u0518\u0519\u051a\u051b\u051c\u051d\u051e\u051f\u0520\u0521\u0522\u0523\u0524\u0525\u0526\u0527\u0528\u0529\u052a\u052b\u052c\u052d\u052e\u052f\u0530\u0557\u0558\u0560\u0588\u058b\u058c\u058d\u058e\u058f\u0590\u05ba\u05c8\u05c9\u05ca\u05cb\u05cc\u05cd\u05ce\u05cf\u05eb\u05ec\u05ed\u05ee\u05ef\u05f5\u05f6\u05f7\u05f8\u05f9\u05fa\u05fb\u05fc\u05fd\u05fe\u05ff\u0604\u0605\u0606\u0607\u0608\u0609\u060a\u0616\u0617\u0618\u0619\u061a\u061c\u061d\u0620\u063b\u063c\u063d\u063e\u063f\u065f\u070e\u074b\u074c\u076e\u076f\u0770\u0771\u0772\u0773\u0774\u0775\u0776\u0777\u0778\u0779\u077a\u077b\u077c\u077d\u077e\u077f\u07b2\u07b3\u07b4\u07b5\u07b6\u07b7\u07b8\u07b9\u07ba\u07bb\u07bc\u07bd\u07be\u07bf\u07c0\u07c1\u07c2\u07c3\u07c4\u07c5\u07c6\u07c7\u07c8\u07c9\u07ca\u07cb\u07cc\u07cd\u07ce\u07cf\u07d0\u07d1\u07d2\u07d3\u07d4\u07d5\u07d6\u07d7\u07d8\u07d9\u07da\u07db\u07dc\u07dd\u07de\u07df\u07e0\u07e1\u07e2\u07e3\u07e4\u07e5\u07e6\u07e7\u07e8\u07e9\u07ea\u07eb\u07ec\u07ed\u07ee\u07ef\u07f0\u07f1\u07f2\u07f3\u07f4\u07f5\u07f6\u07f7\u07f8\u07f9\u07fa\u07fb\u07fc\u07fd\u07fe\u07ff\u0800\u0801\u0802\u0803\u0804\u0805\u0806\u0807\u0808\u0809\u080a\u080b\u080c\u080d\u080e\u080f\u0810\u0811\u0812\u0813\u0814\u0815\u0816\u0817\u0818\u0819\u081a\u081b\u081c\u081d\u081e\u081f\u0820\u0821\u0822\u0823\u0824\u0825\u0826\u0827\u0828\u0829\u082a\u082b\u082c\u082d\u082e\u082f\u0830\u0831\u0832\u0833\u0834\u0835\u0836\u0837\u0838\u0839\u083a\u083b\u083c\u083d\u083e\u083f\u0840\u0841\u0842\u0843\u0844\u0845\u0846\u0847\u0848\u0849\u084a\u084b\u084c\u084d\u084e\u084f\u0850\u0851\u0852\u0853\u0854\u0855\u0856\u0857\u0858\u0859\u085a\u085b\u085c\u085d\u085e\u085f\u0860\u0861\u0862\u0863\u0864\u0865\u0866\u0867\u0868\u0869\u086a\u086b\u086c\u086d\u086e\u086f\u0870\u0871\u0872\u0873\u0874\u0875\u0876\u0877\u0878\u0879\u087a\u087b\u087c\u087d\u087e\u087f\u0880\u0881\u0882\u0883\u0884\u0885\u0886\u0887\u0888\u0889\u088a\u088b\u088c\u088d\u088e\u088f\u0890\u0891\u0892\u0893\u0894\u0895\u0896\u0897\u0898\u0899\u089a\u089b\u089c\u089d\u089e\u089f\u08a0\u08a1\u08a2\u08a3\u08a4\u08a5\u08a6\u08a7\u08a8\u08a9\u08aa\u08ab\u08ac\u08ad\u08ae\u08af\u08b0\u08b1\u08b2\u08b3\u08b4\u08b5\u08b6\u08b7\u08b8\u08b9\u08ba\u08bb\u08bc\u08bd\u08be\u08bf\u08c0\u08c1\u08c2\u08c3\u08c4\u08c5\u08c6\u08c7\u08c8\u08c9\u08ca\u08cb\u08cc\u08cd\u08ce\u08cf\u08d0\u08d1\u08d2\u08d3\u08d4\u08d5\u08d6\u08d7\u08d8\u08d9\u08da\u08db\u08dc\u08dd\u08de\u08df\u08e0\u08e1\u08e2\u08e3\u08e4\u08e5\u08e6\u08e7\u08e8\u08e9\u08ea\u08eb\u08ec\u08ed\u08ee\u08ef\u08f0\u08f1\u08f2\u08f3\u08f4\u08f5\u08f6\u08f7\u08f8\u08f9\u08fa\u08fb\u08fc\u08fd\u08fe\u08ff\u0900\u093a\u093b\u094e\u094f\u0955\u0956\u0957\u0971\u0972\u0973\u0974\u0975\u0976\u0977\u0978\u0979\u097a\u097b\u097c\u097e\u097f\u0980\u0984\u098d\u098e\u0991\u0992\u09a9\u09b1\u09b3\u09b4\u09b5\u09ba\u09bb\u09c5\u09c6\u09c9\u09ca\u09cf\u09d0\u09d1\u09d2\u09d3\u09d4\u09d5\u09d6\u09d8\u09d9\u09da\u09db\u09de\u09e4\u09e5\u09fb\u09fc\u09fd\u09fe\u09ff\u0a00\u0a04\u0a0b\u0a0c\u0a0d\u0a0e\u0a11\u0a12\u0a29\u0a31\u0a34\u0a37\u0a3a\u0a3b\u0a3d\u0a43\u0a44\u0a45\u0a46\u0a49\u0a4a\u0a4e\u0a4f\u0a50\u0a51\u0a52\u0a53\u0a54\u0a55\u0a56\u0a57\u0a58\u0a5d\u0a5f\u0a60\u0a61\u0a62\u0a63\u0a64\u0a65\u0a75\u0a76\u0a77\u0a78\u0a79\u0a7a\u0a7b\u0a7c\u0a7d\u0a7e\u0a7f\u0a80\u0a84\u0a8e\u0a92\u0aa9\u0ab1\u0ab4\u0aba\u0abb\u0ac6\u0aca\u0ace\u0acf\u0ad1\u0ad2\u0ad3\u0ad4\u0ad5\u0ad6\u0ad7\u0ad8\u0ad9\u0ada\u0adb\u0adc\u0add\u0ade\u0adf\u0ae4\u0ae5\u0af0\u0af2\u0af3\u0af4\u0af5\u0af6\u0af7\u0af8\u0af9\u0afa\u0afb\u0afc\u0afd\u0afe\u0aff\u0b00\u0b04\u0b0d\u0b0e\u0b11\u0b12\u0b29\u0b31\u0b34\u0b3a\u0b3b\u0b44\u0b45\u0b46\u0b49\u0b4a\u0b4e\u0b4f\u0b50\u0b51\u0b52\u0b53\u0b54\u0b55\u0b58\u0b59\u0b5a\u0b5b\u0b5e\u0b62\u0b63\u0b64\u0b65\u0b72\u0b73\u0b74\u0b75\u0b76\u0b77\u0b78\u0b79\u0b7a\u0b7b\u0b7c\u0b7d\u0b7e\u0b7f\u0b80\u0b81\u0b84\u0b8b\u0b8c\u0b8d\u0b91\u0b96\u0b97\u0b98\u0b9b\u0b9d\u0ba0\u0ba1\u0ba2\u0ba5\u0ba6\u0ba7\u0bab\u0bac\u0bad\u0bba\u0bbb\u0bbc\u0bbd\u0bc3\u0bc4\u0bc5\u0bc9\u0bce\u0bcf\u0bd0\u0bd1\u0bd2\u0bd3\u0bd4\u0bd5\u0bd6\u0bd8\u0bd9\u0bda\u0bdb\u0bdc\u0bdd\u0bde\u0bdf\u0be0\u0be1\u0be2\u0be3\u0be4\u0be5\u0bfb\u0bfc\u0bfd\u0bfe\u0bff\u0c00\u0c04\u0c0d\u0c11\u0c29\u0c34\u0c3a\u0c3b\u0c3c\u0c3d\u0c45\u0c49\u0c4e\u0c4f\u0c50\u0c51\u0c52\u0c53\u0c54\u0c57\u0c58\u0c59\u0c5a\u0c5b\u0c5c\u0c5d\u0c5e\u0c5f\u0c62\u0c63\u0c64\u0c65\u0c70\u0c71\u0c72\u0c73\u0c74\u0c75\u0c76\u0c77\u0c78\u0c79\u0c7a\u0c7b\u0c7c\u0c7d\u0c7e\u0c7f\u0c80\u0c81\u0c84\u0c8d\u0c91\u0ca9\u0cb4\u0cba\u0cbb\u0cc5\u0cc9\u0cce\u0ccf\u0cd0\u0cd1\u0cd2\u0cd3\u0cd4\u0cd7\u0cd8\u0cd9\u0cda\u0cdb\u0cdc\u0cdd\u0cdf\u0ce2\u0ce3\u0ce4\u0ce5\u0cf0\u0cf1\u0cf2\u0cf3\u0cf4\u0cf5\u0cf6\u0cf7\u0cf8\u0cf9\u0cfa\u0cfb\u0cfc\u0cfd\u0cfe\u0cff\u0d00\u0d01\u0d04\u0d0d\u0d11\u0d29\u0d3a\u0d3b\u0d3c\u0d3d\u0d44\u0d45\u0d49\u0d4e\u0d4f\u0d50\u0d51\u0d52\u0d53\u0d54\u0d55\u0d56\u0d58\u0d59\u0d5a\u0d5b\u0d5c\u0d5d\u0d5e\u0d5f\u0d62\u0d63\u0d64\u0d65\u0d70\u0d71\u0d72\u0d73\u0d74\u0d75\u0d76\u0d77\u0d78\u0d79\u0d7a\u0d7b\u0d7c\u0d7d\u0d7e\u0d7f\u0d80\u0d81\u0d84\u0d97\u0d98\u0d99\u0db2\u0dbc\u0dbe\u0dbf\u0dc7\u0dc8\u0dc9\u0dcb\u0dcc\u0dcd\u0dce\u0dd5\u0dd7\u0de0\u0de1\u0de2\u0de3\u0de4\u0de5\u0de6\u0de7\u0de8\u0de9\u0dea\u0deb\u0dec\u0ded\u0dee\u0def\u0df0\u0df1\u0df5\u0df6\u0df7\u0df8\u0df9\u0dfa\u0dfb\u0dfc\u0dfd\u0dfe\u0dff\u0e00\u0e3b\u0e3c\u0e3d\u0e3e\u0e5c\u0e5d\u0e5e\u0e5f\u0e60\u0e61\u0e62\u0e63\u0e64\u0e65\u0e66\u0e67\u0e68\u0e69\u0e6a\u0e6b\u0e6c\u0e6d\u0e6e\u0e6f\u0e70\u0e71\u0e72\u0e73\u0e74\u0e75\u0e76\u0e77\u0e78\u0e79\u0e7a\u0e7b\u0e7c\u0e7d\u0e7e\u0e7f\u0e80\u0e83\u0e85\u0e86\u0e89\u0e8b\u0e8c\u0e8e\u0e8f\u0e90\u0e91\u0e92\u0e93\u0e98\u0ea0\u0ea4\u0ea6\u0ea8\u0ea9\u0eac\u0eba\u0ebe\u0ebf\u0ec5\u0ec7\u0ece\u0ecf\u0eda\u0edb\u0ede\u0edf\u0ee0\u0ee1\u0ee2\u0ee3\u0ee4\u0ee5\u0ee6\u0ee7\u0ee8\u0ee9\u0eea\u0eeb\u0eec\u0eed\u0eee\u0eef\u0ef0\u0ef1\u0ef2\u0ef3\u0ef4\u0ef5\u0ef6\u0ef7\u0ef8\u0ef9\u0efa\u0efb\u0efc\u0efd\u0efe\u0eff\u0f48\u0f6b\u0f6c\u0f6d\u0f6e\u0f6f\u0f70\u0f8c\u0f8d\u0f8e\u0f8f\u0f98\u0fbd\u0fcd\u0fce\u0fd2\u0fd3\u0fd4\u0fd5\u0fd6\u0fd7\u0fd8\u0fd9\u0fda\u0fdb\u0fdc\u0fdd\u0fde\u0fdf\u0fe0\u0fe1\u0fe2\u0fe3\u0fe4\u0fe5\u0fe6\u0fe7\u0fe8\u0fe9\u0fea\u0feb\u0fec\u0fed\u0fee\u0fef\u0ff0\u0ff1\u0ff2\u0ff3\u0ff4\u0ff5\u0ff6\u0ff7\u0ff8\u0ff9\u0ffa\u0ffb\u0ffc\u0ffd\u0ffe\u0fff\u1022\u1028\u102b\u1033\u1034\u1035\u103a\u103b\u103c\u103d\u103e\u103f\u105a\u105b\u105c\u105d\u105e\u105f\u1060\u1061\u1062\u1063\u1064\u1065\u1066\u1067\u1068\u1069\u106a\u106b\u106c\u106d\u106e\u106f\u1070\u1071\u1072\u1073\u1074\u1075\u1076\u1077\u1078\u1079\u107a\u107b\u107c\u107d\u107e\u107f\u1080\u1081\u1082\u1083\u1084\u1085\u1086\u1087\u1088\u1089\u108a\u108b\u108c\u108d\u108e\u108f\u1090\u1091\u1092\u1093\u1094\u1095\u1096\u1097\u1098\u1099\u109a\u109b\u109c\u109d\u109e\u109f\u10c6\u10c7\u10c8\u10c9\u10ca\u10cb\u10cc\u10cd\u10ce\u10cf\u10fd\u10fe\u10ff\u115a\u115b\u115c\u115d\u115e\u11a3\u11a4\u11a5\u11a6\u11a7\u11fa\u11fb\u11fc\u11fd\u11fe\u11ff\u1249\u124e\u124f\u1257\u1259\u125e\u125f\u1289\u128e\u128f\u12b1\u12b6\u12b7\u12bf\u12c1\u12c6\u12c7\u12d7\u1311\u1316\u1317\u135b\u135c\u135d\u135e\u137d\u137e\u137f\u139a\u139b\u139c\u139d\u139e\u139f\u13f5\u13f6\u13f7\u13f8\u13f9\u13fa\u13fb\u13fc\u13fd\u13fe\u13ff\u1400\u1677\u1678\u1679\u167a\u167b\u167c\u167d\u167e\u167f\u169d\u169e\u169f\u16f1\u16f2\u16f3\u16f4\u16f5\u16f6\u16f7\u16f8\u16f9\u16fa\u16fb\u16fc\u16fd\u16fe\u16ff\u170d\u1715\u1716\u1717\u1718\u1719\u171a\u171b\u171c\u171d\u171e\u171f\u1737\u1738\u1739\u173a\u173b\u173c\u173d\u173e\u173f\u1754\u1755\u1756\u1757\u1758\u1759\u175a\u175b\u175c\u175d\u175e\u175f\u176d\u1771\u1774\u1775\u1776\u1777\u1778\u1779\u177a\u177b\u177c\u177d\u177e\u177f\u17de\u17df\u17ea\u17eb\u17ec\u17ed\u17ee\u17ef\u17fa\u17fb\u17fc\u17fd\u17fe\u17ff\u180f\u181a\u181b\u181c\u181d\u181e\u181f\u1878\u1879\u187a\u187b\u187c\u187d\u187e\u187f\u18aa\u18ab\u18ac\u18ad\u18ae\u18af\u18b0\u18b1\u18b2\u18b3\u18b4\u18b5\u18b6\u18b7\u18b8\u18b9\u18ba\u18bb\u18bc\u18bd\u18be\u18bf\u18c0\u18c1\u18c2\u18c3\u18c4\u18c5\u18c6\u18c7\u18c8\u18c9\u18ca\u18cb\u18cc\u18cd\u18ce\u18cf\u18d0\u18d1\u18d2\u18d3\u18d4\u18d5\u18d6\u18d7\u18d8\u18d9\u18da\u18db\u18dc\u18dd\u18de\u18df\u18e0\u18e1\u18e2\u18e3\u18e4\u18e5\u18e6\u18e7\u18e8\u18e9\u18ea\u18eb\u18ec\u18ed\u18ee\u18ef\u18f0\u18f1\u18f2\u18f3\u18f4\u18f5\u18f6\u18f7\u18f8\u18f9\u18fa\u18fb\u18fc\u18fd\u18fe\u18ff\u191d\u191e\u191f\u192c\u192d\u192e\u192f\u193c\u193d\u193e\u193f\u1941\u1942\u1943\u196e\u196f\u1975\u1976\u1977\u1978\u1979\u197a\u197b\u197c\u197d\u197e\u197f\u19aa\u19ab\u19ac\u19ad\u19ae\u19af\u19ca\u19cb\u19cc\u19cd\u19ce\u19cf\u19da\u19db\u19dc\u19dd\u1a1c\u1a1d\u1a20\u1a21\u1a22\u1a23\u1a24\u1a25\u1a26\u1a27\u1a28\u1a29\u1a2a\u1a2b\u1a2c\u1a2d\u1a2e\u1a2f\u1a30\u1a31\u1a32\u1a33\u1a34\u1a35\u1a36\u1a37\u1a38\u1a39\u1a3a\u1a3b\u1a3c\u1a3d\u1a3e\u1a3f\u1a40\u1a41\u1a42\u1a43\u1a44\u1a45\u1a46\u1a47\u1a48\u1a49\u1a4a\u1a4b\u1a4c\u1a4d\u1a4e\u1a4f\u1a50\u1a51\u1a52\u1a53\u1a54\u1a55\u1a56\u1a57\u1a58\u1a59\u1a5a\u1a5b\u1a5c\u1a5d\u1a5e\u1a5f\u1a60\u1a61\u1a62\u1a63\u1a64\u1a65\u1a66\u1a67\u1a68\u1a69\u1a6a\u1a6b\u1a6c\u1a6d\u1a6e\u1a6f\u1a70\u1a71\u1a72\u1a73\u1a74\u1a75\u1a76\u1a77\u1a78\u1a79\u1a7a\u1a7b\u1a7c\u1a7d\u1a7e\u1a7f\u1a80\u1a81\u1a82\u1a83\u1a84\u1a85\u1a86\u1a87\u1a88\u1a89\u1a8a\u1a8b\u1a8c\u1a8d\u1a8e\u1a8f\u1a90\u1a91\u1a92\u1a93\u1a94\u1a95\u1a96\u1a97\u1a98\u1a99\u1a9a\u1a9b\u1a9c\u1a9d\u1a9e\u1a9f\u1aa0\u1aa1\u1aa2\u1aa3\u1aa4\u1aa5\u1aa6\u1aa7\u1aa8\u1aa9\u1aaa\u1aab\u1aac\u1aad\u1aae\u1aaf\u1ab0\u1ab1\u1ab2\u1ab3\u1ab4\u1ab5\u1ab6\u1ab7\u1ab8\u1ab9\u1aba\u1abb\u1abc\u1abd\u1abe\u1abf\u1ac0\u1ac1\u1ac2\u1ac3\u1ac4\u1ac5\u1ac6\u1ac7\u1ac8\u1ac9\u1aca\u1acb\u1acc\u1acd\u1ace\u1acf\u1ad0\u1ad1\u1ad2\u1ad3\u1ad4\u1ad5\u1ad6\u1ad7\u1ad8\u1ad9\u1ada\u1adb\u1adc\u1add\u1ade\u1adf\u1ae0\u1ae1\u1ae2\u1ae3\u1ae4\u1ae5\u1ae6\u1ae7\u1ae8\u1ae9\u1aea\u1aeb\u1aec\u1aed\u1aee\u1aef\u1af0\u1af1\u1af2\u1af3\u1af4\u1af5\u1af6\u1af7\u1af8\u1af9\u1afa\u1afb\u1afc\u1afd\u1afe\u1aff\u1b00\u1b01\u1b02\u1b03\u1b04\u1b05\u1b06\u1b07\u1b08\u1b09\u1b0a\u1b0b\u1b0c\u1b0d\u1b0e\u1b0f\u1b10\u1b11\u1b12\u1b13\u1b14\u1b15\u1b16\u1b17\u1b18\u1b19\u1b1a\u1b1b\u1b1c\u1b1d\u1b1e\u1b1f\u1b20\u1b21\u1b22\u1b23\u1b24\u1b25\u1b26\u1b27\u1b28\u1b29\u1b2a\u1b2b\u1b2c\u1b2d\u1b2e\u1b2f\u1b30\u1b31\u1b32\u1b33\u1b34\u1b35\u1b36\u1b37\u1b38\u1b39\u1b3a\u1b3b\u1b3c\u1b3d\u1b3e\u1b3f\u1b40\u1b41\u1b42\u1b43\u1b44\u1b45\u1b46\u1b47\u1b48\u1b49\u1b4a\u1b4b\u1b4c\u1b4d\u1b4e\u1b4f\u1b50\u1b51\u1b52\u1b53\u1b54\u1b55\u1b56\u1b57\u1b58\u1b59\u1b5a\u1b5b\u1b5c\u1b5d\u1b5e\u1b5f\u1b60\u1b61\u1b62\u1b63\u1b64\u1b65\u1b66\u1b67\u1b68\u1b69\u1b6a\u1b6b\u1b6c\u1b6d\u1b6e\u1b6f\u1b70\u1b71\u1b72\u1b73\u1b74\u1b75\u1b76\u1b77\u1b78\u1b79\u1b7a\u1b7b\u1b7c\u1b7d\u1b7e\u1b7f\u1b80\u1b81\u1b82\u1b83\u1b84\u1b85\u1b86\u1b87\u1b88\u1b89\u1b8a\u1b8b\u1b8c\u1b8d\u1b8e\u1b8f\u1b90\u1b91\u1b92\u1b93\u1b94\u1b95\u1b96\u1b97\u1b98\u1b99\u1b9a\u1b9b\u1b9c\u1b9d\u1b9e\u1b9f\u1ba0\u1ba1\u1ba2\u1ba3\u1ba4\u1ba5\u1ba6\u1ba7\u1ba8\u1ba9\u1baa\u1bab\u1bac\u1bad\u1bae\u1baf\u1bb0\u1bb1\u1bb2\u1bb3\u1bb4\u1bb5\u1bb6\u1bb7\u1bb8\u1bb9\u1bba\u1bbb\u1bbc\u1bbd\u1bbe\u1bbf\u1bc0\u1bc1\u1bc2\u1bc3\u1bc4\u1bc5\u1bc6\u1bc7\u1bc8\u1bc9\u1bca\u1bcb\u1bcc\u1bcd\u1bce\u1bcf\u1bd0\u1bd1\u1bd2\u1bd3\u1bd4\u1bd5\u1bd6\u1bd7\u1bd8\u1bd9\u1bda\u1bdb\u1bdc\u1bdd\u1bde\u1bdf\u1be0\u1be1\u1be2\u1be3\u1be4\u1be5\u1be6\u1be7\u1be8\u1be9\u1bea\u1beb\u1bec\u1bed\u1bee\u1bef\u1bf0\u1bf1\u1bf2\u1bf3\u1bf4\u1bf5\u1bf6\u1bf7\u1bf8\u1bf9\u1bfa\u1bfb\u1bfc\u1bfd\u1bfe\u1bff\u1c00\u1c01\u1c02\u1c03\u1c04\u1c05\u1c06\u1c07\u1c08\u1c09\u1c0a\u1c0b\u1c0c\u1c0d\u1c0e\u1c0f\u1c10\u1c11\u1c12\u1c13\u1c14\u1c15\u1c16\u1c17\u1c18\u1c19\u1c1a\u1c1b\u1c1c\u1c1d\u1c1e\u1c1f\u1c20\u1c21\u1c22\u1c23\u1c24\u1c25\u1c26\u1c27\u1c28\u1c29\u1c2a\u1c2b\u1c2c\u1c2d\u1c2e\u1c2f\u1c30\u1c31\u1c32\u1c33\u1c34\u1c35\u1c36\u1c37\u1c38\u1c39\u1c3a\u1c3b\u1c3c\u1c3d\u1c3e\u1c3f\u1c40\u1c41\u1c42\u1c43\u1c44\u1c45\u1c46\u1c47\u1c48\u1c49\u1c4a\u1c4b\u1c4c\u1c4d\u1c4e\u1c4f\u1c50\u1c51\u1c52\u1c53\u1c54\u1c55\u1c56\u1c57\u1c58\u1c59\u1c5a\u1c5b\u1c5c\u1c5d\u1c5e\u1c5f\u1c60\u1c61\u1c62\u1c63\u1c64\u1c65\u1c66\u1c67\u1c68\u1c69\u1c6a\u1c6b\u1c6c\u1c6d\u1c6e\u1c6f\u1c70\u1c71\u1c72\u1c73\u1c74\u1c75\u1c76\u1c77\u1c78\u1c79\u1c7a\u1c7b\u1c7c\u1c7d\u1c7e\u1c7f\u1c80\u1c81\u1c82\u1c83\u1c84\u1c85\u1c86\u1c87\u1c88\u1c89\u1c8a\u1c8b\u1c8c\u1c8d\u1c8e\u1c8f\u1c90\u1c91\u1c92\u1c93\u1c94\u1c95\u1c96\u1c97\u1c98\u1c99\u1c9a\u1c9b\u1c9c\u1c9d\u1c9e\u1c9f\u1ca0\u1ca1\u1ca2\u1ca3\u1ca4\u1ca5\u1ca6\u1ca7\u1ca8\u1ca9\u1caa\u1cab\u1cac\u1cad\u1cae\u1caf\u1cb0\u1cb1\u1cb2\u1cb3\u1cb4\u1cb5\u1cb6\u1cb7\u1cb8\u1cb9\u1cba\u1cbb\u1cbc\u1cbd\u1cbe\u1cbf\u1cc0\u1cc1\u1cc2\u1cc3\u1cc4\u1cc5\u1cc6\u1cc7\u1cc8\u1cc9\u1cca\u1ccb\u1ccc\u1ccd\u1cce\u1ccf\u1cd0\u1cd1\u1cd2\u1cd3\u1cd4\u1cd5\u1cd6\u1cd7\u1cd8\u1cd9\u1cda\u1cdb\u1cdc\u1cdd\u1cde\u1cdf\u1ce0\u1ce1\u1ce2\u1ce3\u1ce4\u1ce5\u1ce6\u1ce7\u1ce8\u1ce9\u1cea\u1ceb\u1cec\u1ced\u1cee\u1cef\u1cf0\u1cf1\u1cf2\u1cf3\u1cf4\u1cf5\u1cf6\u1cf7\u1cf8\u1cf9\u1cfa\u1cfb\u1cfc\u1cfd\u1cfe\u1cff\u1dc4\u1dc5\u1dc6\u1dc7\u1dc8\u1dc9\u1dca\u1dcb\u1dcc\u1dcd\u1dce\u1dcf\u1dd0\u1dd1\u1dd2\u1dd3\u1dd4\u1dd5\u1dd6\u1dd7\u1dd8\u1dd9\u1dda\u1ddb\u1ddc\u1ddd\u1dde\u1ddf\u1de0\u1de1\u1de2\u1de3\u1de4\u1de5\u1de6\u1de7\u1de8\u1de9\u1dea\u1deb\u1dec\u1ded\u1dee\u1def\u1df0\u1df1\u1df2\u1df3\u1df4\u1df5\u1df6\u1df7\u1df8\u1df9\u1dfa\u1dfb\u1dfc\u1dfd\u1dfe\u1dff\u1e9c\u1e9d\u1e9e\u1e9f\u1efa\u1efb\u1efc\u1efd\u1efe\u1eff\u1f16\u1f17\u1f1e\u1f1f\u1f46\u1f47\u1f4e\u1f4f\u1f58\u1f5a\u1f5c\u1f5e\u1f7e\u1f7f\u1fb5\u1fc5\u1fd4\u1fd5\u1fdc\u1ff0\u1ff1\u1ff5\u1fff\u2064\u2065\u2066\u2067\u2068\u2069\u2072\u2073\u208f\u2095\u2096\u2097\u2098\u2099\u209a\u209b\u209c\u209d\u209e\u209f\u20b6\u20b7\u20b8\u20b9\u20ba\u20bb\u20bc\u20bd\u20be\u20bf\u20c0\u20c1\u20c2\u20c3\u20c4\u20c5\u20c6\u20c7\u20c8\u20c9\u20ca\u20cb\u20cc\u20cd\u20ce\u20cf\u20ec\u20ed\u20ee\u20ef\u20f0\u20f1\u20f2\u20f3\u20f4\u20f5\u20f6\u20f7\u20f8\u20f9\u20fa\u20fb\u20fc\u20fd\u20fe\u20ff\u214d\u214e\u214f\u2150\u2151\u2152\u2184\u2185\u2186\u2187\u2188\u2189\u218a\u218b\u218c\u218d\u218e\u218f\u23dc\u23dd\u23de\u23df\u23e0\u23e1\u23e2\u23e3\u23e4\u23e5\u23e6\u23e7\u23e8\u23e9\u23ea\u23eb\u23ec\u23ed\u23ee\u23ef\u23f0\u23f1\u23f2\u23f3\u23f4\u23f5\u23f6\u23f7\u23f8\u23f9\u23fa\u23fb\u23fc\u23fd\u23fe\u23ff\u2427\u2428\u2429\u242a\u242b\u242c\u242d\u242e\u242f\u2430\u2431\u2432\u2433\u2434\u2435\u2436\u2437\u2438\u2439\u243a\u243b\u243c\u243d\u243e\u243f\u244b\u244c\u244d\u244e\u244f\u2450\u2451\u2452\u2453\u2454\u2455\u2456\u2457\u2458\u2459\u245a\u245b\u245c\u245d\u245e\u245f\u269d\u269e\u269f\u26b2\u26b3\u26b4\u26b5\u26b6\u26b7\u26b8\u26b9\u26ba\u26bb\u26bc\u26bd\u26be\u26bf\u26c0\u26c1\u26c2\u26c3\u26c4\u26c5\u26c6\u26c7\u26c8\u26c9\u26ca\u26cb\u26cc\u26cd\u26ce\u26cf\u26d0\u26d1\u26d2\u26d3\u26d4\u26d5\u26d6\u26d7\u26d8\u26d9\u26da\u26db\u26dc\u26dd\u26de\u26df\u26e0\u26e1\u26e2\u26e3\u26e4\u26e5\u26e6\u26e7\u26e8\u26e9\u26ea\u26eb\u26ec\u26ed\u26ee\u26ef\u26f0\u26f1\u26f2\u26f3\u26f4\u26f5\u26f6\u26f7\u26f8\u26f9\u26fa\u26fb\u26fc\u26fd\u26fe\u26ff\u2700\u2705\u270a\u270b\u2728\u274c\u274e\u2753\u2754\u2755\u2757\u275f\u2760\u2795\u2796\u2797\u27b0\u27bf\u27c7\u27c8\u27c9\u27ca\u27cb\u27cc\u27cd\u27ce\u27cf\u27ec\u27ed\u27ee\u27ef\u2b14\u2b15\u2b16\u2b17\u2b18\u2b19\u2b1a\u2b1b\u2b1c\u2b1d\u2b1e\u2b1f\u2b20\u2b21\u2b22\u2b23\u2b24\u2b25\u2b26\u2b27\u2b28\u2b29\u2b2a\u2b2b\u2b2c\u2b2d\u2b2e\u2b2f\u2b30\u2b31\u2b32\u2b33\u2b34\u2b35\u2b36\u2b37\u2b38\u2b39\u2b3a\u2b3b\u2b3c\u2b3d\u2b3e\u2b3f\u2b40\u2b41\u2b42\u2b43\u2b44\u2b45\u2b46\u2b47\u2b48\u2b49\u2b4a\u2b4b\u2b4c\u2b4d\u2b4e\u2b4f\u2b50\u2b51\u2b52\u2b53\u2b54\u2b55\u2b56\u2b57\u2b58\u2b59\u2b5a\u2b5b\u2b5c\u2b5d\u2b5e\u2b5f\u2b60\u2b61\u2b62\u2b63\u2b64\u2b65\u2b66\u2b67\u2b68\u2b69\u2b6a\u2b6b\u2b6c\u2b6d\u2b6e\u2b6f\u2b70\u2b71\u2b72\u2b73\u2b74\u2b75\u2b76\u2b77\u2b78\u2b79\u2b7a\u2b7b\u2b7c\u2b7d\u2b7e\u2b7f\u2b80\u2b81\u2b82\u2b83\u2b84\u2b85\u2b86\u2b87\u2b88\u2b89\u2b8a\u2b8b\u2b8c\u2b8d\u2b8e\u2b8f\u2b90\u2b91\u2b92\u2b93\u2b94\u2b95\u2b96\u2b97\u2b98\u2b99\u2b9a\u2b9b\u2b9c\u2b9d\u2b9e\u2b9f\u2ba0\u2ba1\u2ba2\u2ba3\u2ba4\u2ba5\u2ba6\u2ba7\u2ba8\u2ba9\u2baa\u2bab\u2bac\u2bad\u2bae\u2baf\u2bb0\u2bb1\u2bb2\u2bb3\u2bb4\u2bb5\u2bb6\u2bb7\u2bb8\u2bb9\u2bba\u2bbb\u2bbc\u2bbd\u2bbe\u2bbf\u2bc0\u2bc1\u2bc2\u2bc3\u2bc4\u2bc5\u2bc6\u2bc7\u2bc8\u2bc9\u2bca\u2bcb\u2bcc\u2bcd\u2bce\u2bcf\u2bd0\u2bd1\u2bd2\u2bd3\u2bd4\u2bd5\u2bd6\u2bd7\u2bd8\u2bd9\u2bda\u2bdb\u2bdc\u2bdd\u2bde\u2bdf\u2be0\u2be1\u2be2\u2be3\u2be4\u2be5\u2be6\u2be7\u2be8\u2be9\u2bea\u2beb\u2bec\u2bed\u2bee\u2bef\u2bf0\u2bf1\u2bf2\u2bf3\u2bf4\u2bf5\u2bf6\u2bf7\u2bf8\u2bf9\u2bfa\u2bfb\u2bfc\u2bfd\u2bfe\u2bff\u2c2f\u2c5f\u2c60\u2c61\u2c62\u2c63\u2c64\u2c65\u2c66\u2c67\u2c68\u2c69\u2c6a\u2c6b\u2c6c\u2c6d\u2c6e\u2c6f\u2c70\u2c71\u2c72\u2c73\u2c74\u2c75\u2c76\u2c77\u2c78\u2c79\u2c7a\u2c7b\u2c7c\u2c7d\u2c7e\u2c7f\u2ceb\u2cec\u2ced\u2cee\u2cef\u2cf0\u2cf1\u2cf2\u2cf3\u2cf4\u2cf5\u2cf6\u2cf7\u2cf8\u2d26\u2d27\u2d28\u2d29\u2d2a\u2d2b\u2d2c\u2d2d\u2d2e\u2d2f\u2d66\u2d67\u2d68\u2d69\u2d6a\u2d6b\u2d6c\u2d6d\u2d6e\u2d70\u2d71\u2d72\u2d73\u2d74\u2d75\u2d76\u2d77\u2d78\u2d79\u2d7a\u2d7b\u2d7c\u2d7d\u2d7e\u2d7f\u2d97\u2d98\u2d99\u2d9a\u2d9b\u2d9c\u2d9d\u2d9e\u2d9f\u2da7\u2daf\u2db7\u2dbf\u2dc7\u2dcf\u2dd7\u2ddf\u2de0\u2de1\u2de2\u2de3\u2de4\u2de5\u2de6\u2de7\u2de8\u2de9\u2dea\u2deb\u2dec\u2ded\u2dee\u2def\u2df0\u2df1\u2df2\u2df3\u2df4\u2df5\u2df6\u2df7\u2df8\u2df9\u2dfa\u2dfb\u2dfc\u2dfd\u2dfe\u2dff\u2e18\u2e19\u2e1a\u2e1b\u2e1e\u2e1f\u2e20\u2e21\u2e22\u2e23\u2e24\u2e25\u2e26\u2e27\u2e28\u2e29\u2e2a\u2e2b\u2e2c\u2e2d\u2e2e\u2e2f\u2e30\u2e31\u2e32\u2e33\u2e34\u2e35\u2e36\u2e37\u2e38\u2e39\u2e3a\u2e3b\u2e3c\u2e3d\u2e3e\u2e3f\u2e40\u2e41\u2e42\u2e43\u2e44\u2e45\u2e46\u2e47\u2e48\u2e49\u2e4a\u2e4b\u2e4c\u2e4d\u2e4e\u2e4f\u2e50\u2e51\u2e52\u2e53\u2e54\u2e55\u2e56\u2e57\u2e58\u2e59\u2e5a\u2e5b\u2e5c\u2e5d\u2e5e\u2e5f\u2e60\u2e61\u2e62\u2e63\u2e64\u2e65\u2e66\u2e67\u2e68\u2e69\u2e6a\u2e6b\u2e6c\u2e6d\u2e6e\u2e6f\u2e70\u2e71\u2e72\u2e73\u2e74\u2e75\u2e76\u2e77\u2e78\u2e79\u2e7a\u2e7b\u2e7c\u2e7d\u2e7e\u2e7f\u2e9a\u2ef4\u2ef5\u2ef6\u2ef7\u2ef8\u2ef9\u2efa\u2efb\u2efc\u2efd\u2efe\u2eff\u2fd6\u2fd7\u2fd8\u2fd9\u2fda\u2fdb\u2fdc\u2fdd\u2fde\u2fdf\u2fe0\u2fe1\u2fe2\u2fe3\u2fe4\u2fe5\u2fe6\u2fe7\u2fe8\u2fe9\u2fea\u2feb\u2fec\u2fed\u2fee\u2fef\u2ffc\u2ffd\u2ffe\u2fff\u3040\u3097\u3098\u3100\u3101\u3102\u3103\u3104\u312d\u312e\u312f\u3130\u318f\u31b8\u31b9\u31ba\u31bb\u31bc\u31bd\u31be\u31bf\u31d0\u31d1\u31d2\u31d3\u31d4\u31d5\u31d6\u31d7\u31d8\u31d9\u31da\u31db\u31dc\u31dd\u31de\u31df\u31e0\u31e1\u31e2\u31e3\u31e4\u31e5\u31e6\u31e7\u31e8\u31e9\u31ea\u31eb\u31ec\u31ed\u31ee\u31ef\u321f\u3244\u3245\u3246\u3247\u3248\u3249\u324a\u324b\u324c\u324d\u324e\u324f\u32ff\u4db6\u4db7\u4db8\u4db9\u4dba\u4dbb\u4dbc\u4dbd\u4dbe\u4dbf\u9fbc\u9fbd\u9fbe\u9fbf\u9fc0\u9fc1\u9fc2\u9fc3\u9fc4\u9fc5\u9fc6\u9fc7\u9fc8\u9fc9\u9fca\u9fcb\u9fcc\u9fcd\u9fce\u9fcf\u9fd0\u9fd1\u9fd2\u9fd3\u9fd4\u9fd5\u9fd6\u9fd7\u9fd8\u9fd9\u9fda\u9fdb\u9fdc\u9fdd\u9fde\u9fdf\u9fe0\u9fe1\u9fe2\u9fe3\u9fe4\u9fe5\u9fe6\u9fe7\u9fe8\u9fe9\u9fea\u9feb\u9fec\u9fed\u9fee\u9fef\u9ff0\u9ff1\u9ff2\u9ff3\u9ff4\u9ff5\u9ff6\u9ff7\u9ff8\u9ff9\u9ffa\u9ffb\u9ffc\u9ffd\u9ffe\u9fff\ua48d\ua48e\ua48f\ua4c7\ua4c8\ua4c9\ua4ca\ua4cb\ua4cc\ua4cd\ua4ce\ua4cf\ua4d0\ua4d1\ua4d2\ua4d3\ua4d4\ua4d5\ua4d6\ua4d7\ua4d8\ua4d9\ua4da\ua4db\ua4dc\ua4dd\ua4de\ua4df\ua4e0\ua4e1\ua4e2\ua4e3\ua4e4\ua4e5\ua4e6\ua4e7\ua4e8\ua4e9\ua4ea\ua4eb\ua4ec\ua4ed\ua4ee\ua4ef\ua4f0\ua4f1\ua4f2\ua4f3\ua4f4\ua4f5\ua4f6\ua4f7\ua4f8\ua4f9\ua4fa\ua4fb\ua4fc\ua4fd\ua4fe\ua4ff\ua500\ua501\ua502\ua503\ua504\ua505\ua506\ua507\ua508\ua509\ua50a\ua50b\ua50c\ua50d\ua50e\ua50f\ua510\ua511\ua512\ua513\ua514\ua515\ua516\ua517\ua518\ua519\ua51a\ua51b\ua51c\ua51d\ua51e\ua51f\ua520\ua521\ua522\ua523\ua524\ua525\ua526\ua527\ua528\ua529\ua52a\ua52b\ua52c\ua52d\ua52e\ua52f\ua530\ua531\ua532\ua533\ua534\ua535\ua536\ua537\ua538\ua539\ua53a\ua53b\ua53c\ua53d\ua53e\ua53f\ua540\ua541\ua542\ua543\ua544\ua545\ua546\ua547\ua548\ua549\ua54a\ua54b\ua54c\ua54d\ua54e\ua54f\ua550\ua551\ua552\ua553\ua554\ua555\ua556\ua557\ua558\ua559\ua55a\ua55b\ua55c\ua55d\ua55e\ua55f\ua560\ua561\ua562\ua563\ua564\ua565\ua566\ua567\ua568\ua569\ua56a\ua56b\ua56c\ua56d\ua56e\ua56f\ua570\ua571\ua572\ua573\ua574\ua575\ua576\ua577\ua578\ua579\ua57a\ua57b\ua57c\ua57d\ua57e\ua57f\ua580\ua581\ua582\ua583\ua584\ua585\ua586\ua587\ua588\ua589\ua58a\ua58b\ua58c\ua58d\ua58e\ua58f\ua590\ua591\ua592\ua593\ua594\ua595\ua596\ua597\ua598\ua599\ua59a\ua59b\ua59c\ua59d\ua59e\ua59f\ua5a0\ua5a1\ua5a2\ua5a3\ua5a4\ua5a5\ua5a6\ua5a7\ua5a8\ua5a9\ua5aa\ua5ab\ua5ac\ua5ad\ua5ae\ua5af\ua5b0\ua5b1\ua5b2\ua5b3\ua5b4\ua5b5\ua5b6\ua5b7\ua5b8\ua5b9\ua5ba\ua5bb\ua5bc\ua5bd\ua5be\ua5bf\ua5c0\ua5c1\ua5c2\ua5c3\ua5c4\ua5c5\ua5c6\ua5c7\ua5c8\ua5c9\ua5ca\ua5cb\ua5cc\ua5cd\ua5ce\ua5cf\ua5d0\ua5d1\ua5d2\ua5d3\ua5d4\ua5d5\ua5d6\ua5d7\ua5d8\ua5d9\ua5da\ua5db\ua5dc\ua5dd\ua5de\ua5df\ua5e0\ua5e1\ua5e2\ua5e3\ua5e4\ua5e5\ua5e6\ua5e7\ua5e8\ua5e9\ua5ea\ua5eb\ua5ec\ua5ed\ua5ee\ua5ef\ua5f0\ua5f1\ua5f2\ua5f3\ua5f4\ua5f5\ua5f6\ua5f7\ua5f8\ua5f9\ua5fa\ua5fb\ua5fc\ua5fd\ua5fe\ua5ff\ua600\ua601\ua602\ua603\ua604\ua605\ua606\ua607\ua608\ua609\ua60a\ua60b\ua60c\ua60d\ua60e\ua60f\ua610\ua611\ua612\ua613\ua614\ua615\ua616\ua617\ua618\ua619\ua61a\ua61b\ua61c\ua61d\ua61e\ua61f\ua620\ua621\ua622\ua623\ua624\ua625\ua626\ua627\ua628\ua629\ua62a\ua62b\ua62c\ua62d\ua62e\ua62f\ua630\ua631\ua632\ua633\ua634\ua635\ua636\ua637\ua638\ua639\ua63a\ua63b\ua63c\ua63d\ua63e\ua63f\ua640\ua641\ua642\ua643\ua644\ua645\ua646\ua647\ua648\ua649\ua64a\ua64b\ua64c\ua64d\ua64e\ua64f\ua650\ua651\ua652\ua653\ua654\ua655\ua656\ua657\ua658\ua659\ua65a\ua65b\ua65c\ua65d\ua65e\ua65f\ua660\ua661\ua662\ua663\ua664\ua665\ua666\ua667\ua668\ua669\ua66a\ua66b\ua66c\ua66d\ua66e\ua66f\ua670\ua671\ua672\ua673\ua674\ua675\ua676\ua677\ua678\ua679\ua67a\ua67b\ua67c\ua67d\ua67e\ua67f\ua680\ua681\ua682\ua683\ua684\ua685\ua686\ua687\ua688\ua689\ua68a\ua68b\ua68c\ua68d\ua68e\ua68f\ua690\ua691\ua692\ua693\ua694\ua695\ua696\ua697\ua698\ua699\ua69a\ua69b\ua69c\ua69d\ua69e\ua69f\ua6a0\ua6a1\ua6a2\ua6a3\ua6a4\ua6a5\ua6a6\ua6a7\ua6a8\ua6a9\ua6aa\ua6ab\ua6ac\ua6ad\ua6ae\ua6af\ua6b0\ua6b1\ua6b2\ua6b3\ua6b4\ua6b5\ua6b6\ua6b7\ua6b8\ua6b9\ua6ba\ua6bb\ua6bc\ua6bd\ua6be\ua6bf\ua6c0\ua6c1\ua6c2\ua6c3\ua6c4\ua6c5\ua6c6\ua6c7\ua6c8\ua6c9\ua6ca\ua6cb\ua6cc\ua6cd\ua6ce\ua6cf\ua6d0\ua6d1\ua6d2\ua6d3\ua6d4\ua6d5\ua6d6\ua6d7\ua6d8\ua6d9\ua6da\ua6db\ua6dc\ua6dd\ua6de\ua6df\ua6e0\ua6e1\ua6e2\ua6e3\ua6e4\ua6e5\ua6e6\ua6e7\ua6e8\ua6e9\ua6ea\ua6eb\ua6ec\ua6ed\ua6ee\ua6ef\ua6f0\ua6f1\ua6f2\ua6f3\ua6f4\ua6f5\ua6f6\ua6f7\ua6f8\ua6f9\ua6fa\ua6fb\ua6fc\ua6fd\ua6fe\ua6ff\ua717\ua718\ua719\ua71a\ua71b\ua71c\ua71d\ua71e\ua71f\ua720\ua721\ua722\ua723\ua724\ua725\ua726\ua727\ua728\ua729\ua72a\ua72b\ua72c\ua72d\ua72e\ua72f\ua730\ua731\ua732\ua733\ua734\ua735\ua736\ua737\ua738\ua739\ua73a\ua73b\ua73c\ua73d\ua73e\ua73f\ua740\ua741\ua742\ua743\ua744\ua745\ua746\ua747\ua748\ua749\ua74a\ua74b\ua74c\ua74d\ua74e\ua74f\ua750\ua751\ua752\ua753\ua754\ua755\ua756\ua757\ua758\ua759\ua75a\ua75b\ua75c\ua75d\ua75e\ua75f\ua760\ua761\ua762\ua763\ua764\ua765\ua766\ua767\ua768\ua769\ua76a\ua76b\ua76c\ua76d\ua76e\ua76f\ua770\ua771\ua772\ua773\ua774\ua775\ua776\ua777\ua778\ua779\ua77a\ua77b\ua77c\ua77d\ua77e\ua77f\ua780\ua781\ua782\ua783\ua784\ua785\ua786\ua787\ua788\ua789\ua78a\ua78b\ua78c\ua78d\ua78e\ua78f\ua790\ua791\ua792\ua793\ua794\ua795\ua796\ua797\ua798\ua799\ua79a\ua79b\ua79c\ua79d\ua79e\ua79f\ua7a0\ua7a1\ua7a2\ua7a3\ua7a4\ua7a5\ua7a6\ua7a7\ua7a8\ua7a9\ua7aa\ua7ab\ua7ac\ua7ad\ua7ae\ua7af\ua7b0\ua7b1\ua7b2\ua7b3\ua7b4\ua7b5\ua7b6\ua7b7\ua7b8\ua7b9\ua7ba\ua7bb\ua7bc\ua7bd\ua7be\ua7bf\ua7c0\ua7c1\ua7c2\ua7c3\ua7c4\ua7c5\ua7c6\ua7c7\ua7c8\ua7c9\ua7ca\ua7cb\ua7cc\ua7cd\ua7ce\ua7cf\ua7d0\ua7d1\ua7d2\ua7d3\ua7d4\ua7d5\ua7d6\ua7d7\ua7d8\ua7d9\ua7da\ua7db\ua7dc\ua7dd\ua7de\ua7df\ua7e0\ua7e1\ua7e2\ua7e3\ua7e4\ua7e5\ua7e6\ua7e7\ua7e8\ua7e9\ua7ea\ua7eb\ua7ec\ua7ed\ua7ee\ua7ef\ua7f0\ua7f1\ua7f2\ua7f3\ua7f4\ua7f5\ua7f6\ua7f7\ua7f8\ua7f9\ua7fa\ua7fb\ua7fc\ua7fd\ua7fe\ua7ff\ua82c\ua82d\ua82e\ua82f\ua830\ua831\ua832\ua833\ua834\ua835\ua836\ua837\ua838\ua839\ua83a\ua83b\ua83c\ua83d\ua83e\ua83f\ua840\ua841\ua842\ua843\ua844\ua845\ua846\ua847\ua848\ua849\ua84a\ua84b\ua84c\ua84d\ua84e\ua84f\ua850\ua851\ua852\ua853\ua854\ua855\ua856\ua857\ua858\ua859\ua85a\ua85b\ua85c\ua85d\ua85e\ua85f\ua860\ua861\ua862\ua863\ua864\ua865\ua866\ua867\ua868\ua869\ua86a\ua86b\ua86c\ua86d\ua86e\ua86f\ua870\ua871\ua872\ua873\ua874\ua875\ua876\ua877\ua878\ua879\ua87a\ua87b\ua87c\ua87d\ua87e\ua87f\ua880\ua881\ua882\ua883\ua884\ua885\ua886\ua887\ua888\ua889\ua88a\ua88b\ua88c\ua88d\ua88e\ua88f\ua890\ua891\ua892\ua893\ua894\ua895\ua896\ua897\ua898\ua899\ua89a\ua89b\ua89c\ua89d\ua89e\ua89f\ua8a0\ua8a1\ua8a2\ua8a3\ua8a4\ua8a5\ua8a6\ua8a7\ua8a8\ua8a9\ua8aa\ua8ab\ua8ac\ua8ad\ua8ae\ua8af\ua8b0\ua8b1\ua8b2\ua8b3\ua8b4\ua8b5\ua8b6\ua8b7\ua8b8\ua8b9\ua8ba\ua8bb\ua8bc\ua8bd\ua8be\ua8bf\ua8c0\ua8c1\ua8c2\ua8c3\ua8c4\ua8c5\ua8c6\ua8c7\ua8c8\ua8c9\ua8ca\ua8cb\ua8cc\ua8cd\ua8ce\ua8cf\ua8d0\ua8d1\ua8d2\ua8d3\ua8d4\ua8d5\ua8d6\ua8d7\ua8d8\ua8d9\ua8da\ua8db\ua8dc\ua8dd\ua8de\ua8df\ua8e0\ua8e1\ua8e2\ua8e3\ua8e4\ua8e5\ua8e6\ua8e7\ua8e8\ua8e9\ua8ea\ua8eb\ua8ec\ua8ed\ua8ee\ua8ef\ua8f0\ua8f1\ua8f2\ua8f3\ua8f4\ua8f5\ua8f6\ua8f7\ua8f8\ua8f9\ua8fa\ua8fb\ua8fc\ua8fd\ua8fe\ua8ff\ua900\ua901\ua902\ua903\ua904\ua905\ua906\ua907\ua908\ua909\ua90a\ua90b\ua90c\ua90d\ua90e\ua90f\ua910\ua911\ua912\ua913\ua914\ua915\ua916\ua917\ua918\ua919\ua91a\ua91b\ua91c\ua91d\ua91e\ua91f\ua920\ua921\ua922\ua923\ua924\ua925\ua926\ua927\ua928\ua929\ua92a\ua92b\ua92c\ua92d\ua92e\ua92f\ua930\ua931\ua932\ua933\ua934\ua935\ua936\ua937\ua938\ua939\ua93a\ua93b\ua93c\ua93d\ua93e\ua93f\ua940\ua941\ua942\ua943\ua944\ua945\ua946\ua947\ua948\ua949\ua94a\ua94b\ua94c\ua94d\ua94e\ua94f\ua950\ua951\ua952\ua953\ua954\ua955\ua956\ua957\ua958\ua959\ua95a\ua95b\ua95c\ua95d\ua95e\ua95f\ua960\ua961\ua962\ua963\ua964\ua965\ua966\ua967\ua968\ua969\ua96a\ua96b\ua96c\ua96d\ua96e\ua96f\ua970\ua971\ua972\ua973\ua974\ua975\ua976\ua977\ua978\ua979\ua97a\ua97b\ua97c\ua97d\ua97e\ua97f\ua980\ua981\ua982\ua983\ua984\ua985\ua986\ua987\ua988\ua989\ua98a\ua98b\ua98c\ua98d\ua98e\ua98f\ua990\ua991\ua992\ua993\ua994\ua995\ua996\ua997\ua998\ua999\ua99a\ua99b\ua99c\ua99d\ua99e\ua99f\ua9a0\ua9a1\ua9a2\ua9a3\ua9a4\ua9a5\ua9a6\ua9a7\ua9a8\ua9a9\ua9aa\ua9ab\ua9ac\ua9ad\ua9ae\ua9af\ua9b0\ua9b1\ua9b2\ua9b3\ua9b4\ua9b5\ua9b6\ua9b7\ua9b8\ua9b9\ua9ba\ua9bb\ua9bc\ua9bd\ua9be\ua9bf\ua9c0\ua9c1\ua9c2\ua9c3\ua9c4\ua9c5\ua9c6\ua9c7\ua9c8\ua9c9\ua9ca\ua9cb\ua9cc\ua9cd\ua9ce\ua9cf\ua9d0\ua9d1\ua9d2\ua9d3\ua9d4\ua9d5\ua9d6\ua9d7\ua9d8\ua9d9\ua9da\ua9db\ua9dc\ua9dd\ua9de\ua9df\ua9e0\ua9e1\ua9e2\ua9e3\ua9e4\ua9e5\ua9e6\ua9e7\ua9e8\ua9e9\ua9ea\ua9eb\ua9ec\ua9ed\ua9ee\ua9ef\ua9f0\ua9f1\ua9f2\ua9f3\ua9f4\ua9f5\ua9f6\ua9f7\ua9f8\ua9f9\ua9fa\ua9fb\ua9fc\ua9fd\ua9fe\ua9ff\uaa00\uaa01\uaa02\uaa03\uaa04\uaa05\uaa06\uaa07\uaa08\uaa09\uaa0a\uaa0b\uaa0c\uaa0d\uaa0e\uaa0f\uaa10\uaa11\uaa12\uaa13\uaa14\uaa15\uaa16\uaa17\uaa18\uaa19\uaa1a\uaa1b\uaa1c\uaa1d\uaa1e\uaa1f\uaa20\uaa21\uaa22\uaa23\uaa24\uaa25\uaa26\uaa27\uaa28\uaa29\uaa2a\uaa2b\uaa2c\uaa2d\uaa2e\uaa2f\uaa30\uaa31\uaa32\uaa33\uaa34\uaa35\uaa36\uaa37\uaa38\uaa39\uaa3a\uaa3b\uaa3c\uaa3d\uaa3e\uaa3f\uaa40\uaa41\uaa42\uaa43\uaa44\uaa45\uaa46\uaa47\uaa48\uaa49\uaa4a\uaa4b\uaa4c\uaa4d\uaa4e\uaa4f\uaa50\uaa51\uaa52\uaa53\uaa54\uaa55\uaa56\uaa57\uaa58\uaa59\uaa5a\uaa5b\uaa5c\uaa5d\uaa5e\uaa5f\uaa60\uaa61\uaa62\uaa63\uaa64\uaa65\uaa66\uaa67\uaa68\uaa69\uaa6a\uaa6b\uaa6c\uaa6d\uaa6e\uaa6f\uaa70\uaa71\uaa72\uaa73\uaa74\uaa75\uaa76\uaa77\uaa78\uaa79\uaa7a\uaa7b\uaa7c\uaa7d\uaa7e\uaa7f\uaa80\uaa81\uaa82\uaa83\uaa84\uaa85\uaa86\uaa87\uaa88\uaa89\uaa8a\uaa8b\uaa8c\uaa8d\uaa8e\uaa8f\uaa90\uaa91\uaa92\uaa93\uaa94\uaa95\uaa96\uaa97\uaa98\uaa99\uaa9a\uaa9b\uaa9c\uaa9d\uaa9e\uaa9f\uaaa0\uaaa1\uaaa2\uaaa3\uaaa4\uaaa5\uaaa6\uaaa7\uaaa8\uaaa9\uaaaa\uaaab\uaaac\uaaad\uaaae\uaaaf\uaab0\uaab1\uaab2\uaab3\uaab4\uaab5\uaab6\uaab7\uaab8\uaab9\uaaba\uaabb\uaabc\uaabd\uaabe\uaabf\uaac0\uaac1\uaac2\uaac3\uaac4\uaac5\uaac6\uaac7\uaac8\uaac9\uaaca\uaacb\uaacc\uaacd\uaace\uaacf\uaad0\uaad1\uaad2\uaad3\uaad4\uaad5\uaad6\uaad7\uaad8\uaad9\uaada\uaadb\uaadc\uaadd\uaade\uaadf\uaae0\uaae1\uaae2\uaae3\uaae4\uaae5\uaae6\uaae7\uaae8\uaae9\uaaea\uaaeb\uaaec\uaaed\uaaee\uaaef\uaaf0\uaaf1\uaaf2\uaaf3\uaaf4\uaaf5\uaaf6\uaaf7\uaaf8\uaaf9\uaafa\uaafb\uaafc\uaafd\uaafe\uaaff\uab00\uab01\uab02\uab03\uab04\uab05\uab06\uab07\uab08\uab09\uab0a\uab0b\uab0c\uab0d\uab0e\uab0f\uab10\uab11\uab12\uab13\uab14\uab15\uab16\uab17\uab18\uab19\uab1a\uab1b\uab1c\uab1d\uab1e\uab1f\uab20\uab21\uab22\uab23\uab24\uab25\uab26\uab27\uab28\uab29\uab2a\uab2b\uab2c\uab2d\uab2e\uab2f\uab30\uab31\uab32\uab33\uab34\uab35\uab36\uab37\uab38\uab39\uab3a\uab3b\uab3c\uab3d\uab3e\uab3f\uab40\uab41\uab42\uab43\uab44\uab45\uab46\uab47\uab48\uab49\uab4a\uab4b\uab4c\uab4d\uab4e\uab4f\uab50\uab51\uab52\uab53\uab54\uab55\uab56\uab57\uab58\uab59\uab5a\uab5b\uab5c\uab5d\uab5e\uab5f\uab60\uab61\uab62\uab63\uab64\uab65\uab66\uab67\uab68\uab69\uab6a\uab6b\uab6c\uab6d\uab6e\uab6f\uab70\uab71\uab72\uab73\uab74\uab75\uab76\uab77\uab78\uab79\uab7a\uab7b\uab7c\uab7d\uab7e\uab7f\uab80\uab81\uab82\uab83\uab84\uab85\uab86\uab87\uab88\uab89\uab8a\uab8b\uab8c\uab8d\uab8e\uab8f\uab90\uab91\uab92\uab93\uab94\uab95\uab96\uab97\uab98\uab99\uab9a\uab9b\uab9c\uab9d\uab9e\uab9f\uaba0\uaba1\uaba2\uaba3\uaba4\uaba5\uaba6\uaba7\uaba8\uaba9\uabaa\uabab\uabac\uabad\uabae\uabaf\uabb0\uabb1\uabb2\uabb3\uabb4\uabb5\uabb6\uabb7\uabb8\uabb9\uabba\uabbb\uabbc\uabbd\uabbe\uabbf\uabc0\uabc1\uabc2\uabc3\uabc4\uabc5\uabc6\uabc7\uabc8\uabc9\uabca\uabcb\uabcc\uabcd\uabce\uabcf\uabd0\uabd1\uabd2\uabd3\uabd4\uabd5\uabd6\uabd7\uabd8\uabd9\uabda\uabdb\uabdc\uabdd\uabde\uabdf\uabe0\uabe1\uabe2\uabe3\uabe4\uabe5\uabe6\uabe7\uabe8\uabe9\uabea\uabeb\uabec\uabed\uabee\uabef\uabf0\uabf1\uabf2\uabf3\uabf4\uabf5\uabf6\uabf7\uabf8\uabf9\uabfa\uabfb\uabfc\uabfd\uabfe\uabff\ud7a4\ud7a5\ud7a6\ud7a7\ud7a8\ud7a9\ud7aa\ud7ab\ud7ac\ud7ad\ud7ae\ud7af\ud7b0\ud7b1\ud7b2\ud7b3\ud7b4\ud7b5\ud7b6\ud7b7\ud7b8\ud7b9\ud7ba\ud7bb\ud7bc\ud7bd\ud7be\ud7bf\ud7c0\ud7c1\ud7c2\ud7c3\ud7c4\ud7c5\ud7c6\ud7c7\ud7c8\ud7c9\ud7ca\ud7cb\ud7cc\ud7cd\ud7ce\ud7cf\ud7d0\ud7d1\ud7d2\ud7d3\ud7d4\ud7d5\ud7d6\ud7d7\ud7d8\ud7d9\ud7da\ud7db\ud7dc\ud7dd\ud7de\ud7df\ud7e0\ud7e1\ud7e2\ud7e3\ud7e4\ud7e5\ud7e6\ud7e7\ud7e8\ud7e9\ud7ea\ud7eb\ud7ec\ud7ed\ud7ee\ud7ef\ud7f0\ud7f1\ud7f2\ud7f3\ud7f4\ud7f5\ud7f6\ud7f7\ud7f8\ud7f9\ud7fa\ud7fb\ud7fc\ud7fd\ud7fe\ud7ff\ufa2e\ufa2f\ufa6b\ufa6c\ufa6d\ufa6e\ufa6f\ufada\ufadb\ufadc\ufadd\ufade\ufadf\ufae0\ufae1\ufae2\ufae3\ufae4\ufae5\ufae6\ufae7\ufae8\ufae9\ufaea\ufaeb\ufaec\ufaed\ufaee\ufaef\ufaf0\ufaf1\ufaf2\ufaf3\ufaf4\ufaf5\ufaf6\ufaf7\ufaf8\ufaf9\ufafa\ufafb\ufafc\ufafd\ufafe\ufaff\ufb07\ufb08\ufb09\ufb0a\ufb0b\ufb0c\ufb0d\ufb0e\ufb0f\ufb10\ufb11\ufb12\ufb18\ufb19\ufb1a\ufb1b\ufb1c\ufb37\ufb3d\ufb3f\ufb42\ufb45\ufbb2\ufbb3\ufbb4\ufbb5\ufbb6\ufbb7\ufbb8\ufbb9\ufbba\ufbbb\ufbbc\ufbbd\ufbbe\ufbbf\ufbc0\ufbc1\ufbc2\ufbc3\ufbc4\ufbc5\ufbc6\ufbc7\ufbc8\ufbc9\ufbca\ufbcb\ufbcc\ufbcd\ufbce\ufbcf\ufbd0\ufbd1\ufbd2\ufd40\ufd41\ufd42\ufd43\ufd44\ufd45\ufd46\ufd47\ufd48\ufd49\ufd4a\ufd4b\ufd4c\ufd4d\ufd4e\ufd4f\ufd90\ufd91\ufdc8\ufdc9\ufdca\ufdcb\ufdcc\ufdcd\ufdce\ufdcf\ufdd0\ufdd1\ufdd2\ufdd3\ufdd4\ufdd5\ufdd6\ufdd7\ufdd8\ufdd9\ufdda\ufddb\ufddc\ufddd\ufdde\ufddf\ufde0\ufde1\ufde2\ufde3\ufde4\ufde5\ufde6\ufde7\ufde8\ufde9\ufdea\ufdeb\ufdec\ufded\ufdee\ufdef\ufdfe\ufdff\ufe1a\ufe1b\ufe1c\ufe1d\ufe1e\ufe1f\ufe24\ufe25\ufe26\ufe27\ufe28\ufe29\ufe2a\ufe2b\ufe2c\ufe2d\ufe2e\ufe2f\ufe53\ufe67\ufe6c\ufe6d\ufe6e\ufe6f\ufe75\ufefd\ufefe\uff00\uffbf\uffc0\uffc1\uffc8\uffc9\uffd0\uffd1\uffd8\uffd9\uffdd\uffde\uffdf\uffe7\uffef\ufff0\ufff1\ufff2\ufff3\ufff4\ufff5\ufff6\ufff7\ufff8\ufffe'
+
+Co = u'\ue000\ue001\ue002\ue003\ue004\ue005\ue006\ue007\ue008\ue009\ue00a\ue00b\ue00c\ue00d\ue00e\ue00f\ue010\ue011\ue012\ue013\ue014\ue015\ue016\ue017\ue018\ue019\ue01a\ue01b\ue01c\ue01d\ue01e\ue01f\ue020\ue021\ue022\ue023\ue024\ue025\ue026\ue027\ue028\ue029\ue02a\ue02b\ue02c\ue02d\ue02e\ue02f\ue030\ue031\ue032\ue033\ue034\ue035\ue036\ue037\ue038\ue039\ue03a\ue03b\ue03c\ue03d\ue03e\ue03f\ue040\ue041\ue042\ue043\ue044\ue045\ue046\ue047\ue048\ue049\ue04a\ue04b\ue04c\ue04d\ue04e\ue04f\ue050\ue051\ue052\ue053\ue054\ue055\ue056\ue057\ue058\ue059\ue05a\ue05b\ue05c\ue05d\ue05e\ue05f\ue060\ue061\ue062\ue063\ue064\ue065\ue066\ue067\ue068\ue069\ue06a\ue06b\ue06c\ue06d\ue06e\ue06f\ue070\ue071\ue072\ue073\ue074\ue075\ue076\ue077\ue078\ue079\ue07a\ue07b\ue07c\ue07d\ue07e\ue07f\ue080\ue081\ue082\ue083\ue084\ue085\ue086\ue087\ue088\ue089\ue08a\ue08b\ue08c\ue08d\ue08e\ue08f\ue090\ue091\ue092\ue093\ue094\ue095\ue096\ue097\ue098\ue099\ue09a\ue09b\ue09c\ue09d\ue09e\ue09f\ue0a0\ue0a1\ue0a2\ue0a3\ue0a4\ue0a5\ue0a6\ue0a7\ue0a8\ue0a9\ue0aa\ue0ab\ue0ac\ue0ad\ue0ae\ue0af\ue0b0\ue0b1\ue0b2\ue0b3\ue0b4\ue0b5\ue0b6\ue0b7\ue0b8\ue0b9\ue0ba\ue0bb\ue0bc\ue0bd\ue0be\ue0bf\ue0c0\ue0c1\ue0c2\ue0c3\ue0c4\ue0c5\ue0c6\ue0c7\ue0c8\ue0c9\ue0ca\ue0cb\ue0cc\ue0cd\ue0ce\ue0cf\ue0d0\ue0d1\ue0d2\ue0d3\ue0d4\ue0d5\ue0d6\ue0d7\ue0d8\ue0d9\ue0da\ue0db\ue0dc\ue0dd\ue0de\ue0df\ue0e0\ue0e1\ue0e2\ue0e3\ue0e4\ue0e5\ue0e6\ue0e7\ue0e8\ue0e9\ue0ea\ue0eb\ue0ec\ue0ed\ue0ee\ue0ef\ue0f0\ue0f1\ue0f2\ue0f3\ue0f4\ue0f5\ue0f6\ue0f7\ue0f8\ue0f9\ue0fa\ue0fb\ue0fc\ue0fd\ue0fe\ue0ff\ue100\ue101\ue102\ue103\ue104\ue105\ue106\ue107\ue108\ue109\ue10a\ue10b\ue10c\ue10d\ue10e\ue10f\ue110\ue111\ue112\ue113\ue114\ue115\ue116\ue117\ue118\ue119\ue11a\ue11b\ue11c\ue11d\ue11e\ue11f\ue120\ue121\ue122\ue123\ue124\ue125\ue126\ue127\ue128\ue129\ue12a\ue12b\ue12c\ue12d\ue12e\ue12f\ue130\ue131\ue132\ue133\ue134\ue135\ue136\ue137\ue138\ue139\ue13a\ue13b\ue13c\ue13d\ue13e\ue13f\ue140\ue141\ue142\ue143\ue144\ue145\ue146\ue147\ue148\ue149\ue14a\ue14b\ue14c\ue14d\ue14e\ue14f\ue150\ue151\ue152\ue153\ue154\ue155\ue156\ue157\ue158\ue159\ue15a\ue15b\ue15c\ue15d\ue15e\ue15f\ue160\ue161\ue162\ue163\ue164\ue165\ue166\ue167\ue168\ue169\ue16a\ue16b\ue16c\ue16d\ue16e\ue16f\ue170\ue171\ue172\ue173\ue174\ue175\ue176\ue177\ue178\ue179\ue17a\ue17b\ue17c\ue17d\ue17e\ue17f\ue180\ue181\ue182\ue183\ue184\ue185\ue186\ue187\ue188\ue189\ue18a\ue18b\ue18c\ue18d\ue18e\ue18f\ue190\ue191\ue192\ue193\ue194\ue195\ue196\ue197\ue198\ue199\ue19a\ue19b\ue19c\ue19d\ue19e\ue19f\ue1a0\ue1a1\ue1a2\ue1a3\ue1a4\ue1a5\ue1a6\ue1a7\ue1a8\ue1a9\ue1aa\ue1ab\ue1ac\ue1ad\ue1ae\ue1af\ue1b0\ue1b1\ue1b2\ue1b3\ue1b4\ue1b5\ue1b6\ue1b7\ue1b8\ue1b9\ue1ba\ue1bb\ue1bc\ue1bd\ue1be\ue1bf\ue1c0\ue1c1\ue1c2\ue1c3\ue1c4\ue1c5\ue1c6\ue1c7\ue1c8\ue1c9\ue1ca\ue1cb\ue1cc\ue1cd\ue1ce\ue1cf\ue1d0\ue1d1\ue1d2\ue1d3\ue1d4\ue1d5\ue1d6\ue1d7\ue1d8\ue1d9\ue1da\ue1db\ue1dc\ue1dd\ue1de\ue1df\ue1e0\ue1e1\ue1e2\ue1e3\ue1e4\ue1e5\ue1e6\ue1e7\ue1e8\ue1e9\ue1ea\ue1eb\ue1ec\ue1ed\ue1ee\ue1ef\ue1f0\ue1f1\ue1f2\ue1f3\ue1f4\ue1f5\ue1f6\ue1f7\ue1f8\ue1f9\ue1fa\ue1fb\ue1fc\ue1fd\ue1fe\ue1ff\ue200\ue201\ue202\ue203\ue204\ue205\ue206\ue207\ue208\ue209\ue20a\ue20b\ue20c\ue20d\ue20e\ue20f\ue210\ue211\ue212\ue213\ue214\ue215\ue216\ue217\ue218\ue219\ue21a\ue21b\ue21c\ue21d\ue21e\ue21f\ue220\ue221\ue222\ue223\ue224\ue225\ue226\ue227\ue228\ue229\ue22a\ue22b\ue22c\ue22d\ue22e\ue22f\ue230\ue231\ue232\ue233\ue234\ue235\ue236\ue237\ue238\ue239\ue23a\ue23b\ue23c\ue23d\ue23e\ue23f\ue240\ue241\ue242\ue243\ue244\ue245\ue246\ue247\ue248\ue249\ue24a\ue24b\ue24c\ue24d\ue24e\ue24f\ue250\ue251\ue252\ue253\ue254\ue255\ue256\ue257\ue258\ue259\ue25a\ue25b\ue25c\ue25d\ue25e\ue25f\ue260\ue261\ue262\ue263\ue264\ue265\ue266\ue267\ue268\ue269\ue26a\ue26b\ue26c\ue26d\ue26e\ue26f\ue270\ue271\ue272\ue273\ue274\ue275\ue276\ue277\ue278\ue279\ue27a\ue27b\ue27c\ue27d\ue27e\ue27f\ue280\ue281\ue282\ue283\ue284\ue285\ue286\ue287\ue288\ue289\ue28a\ue28b\ue28c\ue28d\ue28e\ue28f\ue290\ue291\ue292\ue293\ue294\ue295\ue296\ue297\ue298\ue299\ue29a\ue29b\ue29c\ue29d\ue29e\ue29f\ue2a0\ue2a1\ue2a2\ue2a3\ue2a4\ue2a5\ue2a6\ue2a7\ue2a8\ue2a9\ue2aa\ue2ab\ue2ac\ue2ad\ue2ae\ue2af\ue2b0\ue2b1\ue2b2\ue2b3\ue2b4\ue2b5\ue2b6\ue2b7\ue2b8\ue2b9\ue2ba\ue2bb\ue2bc\ue2bd\ue2be\ue2bf\ue2c0\ue2c1\ue2c2\ue2c3\ue2c4\ue2c5\ue2c6\ue2c7\ue2c8\ue2c9\ue2ca\ue2cb\ue2cc\ue2cd\ue2ce\ue2cf\ue2d0\ue2d1\ue2d2\ue2d3\ue2d4\ue2d5\ue2d6\ue2d7\ue2d8\ue2d9\ue2da\ue2db\ue2dc\ue2dd\ue2de\ue2df\ue2e0\ue2e1\ue2e2\ue2e3\ue2e4\ue2e5\ue2e6\ue2e7\ue2e8\ue2e9\ue2ea\ue2eb\ue2ec\ue2ed\ue2ee\ue2ef\ue2f0\ue2f1\ue2f2\ue2f3\ue2f4\ue2f5\ue2f6\ue2f7\ue2f8\ue2f9\ue2fa\ue2fb\ue2fc\ue2fd\ue2fe\ue2ff\ue300\ue301\ue302\ue303\ue304\ue305\ue306\ue307\ue308\ue309\ue30a\ue30b\ue30c\ue30d\ue30e\ue30f\ue310\ue311\ue312\ue313\ue314\ue315\ue316\ue317\ue318\ue319\ue31a\ue31b\ue31c\ue31d\ue31e\ue31f\ue320\ue321\ue322\ue323\ue324\ue325\ue326\ue327\ue328\ue329\ue32a\ue32b\ue32c\ue32d\ue32e\ue32f\ue330\ue331\ue332\ue333\ue334\ue335\ue336\ue337\ue338\ue339\ue33a\ue33b\ue33c\ue33d\ue33e\ue33f\ue340\ue341\ue342\ue343\ue344\ue345\ue346\ue347\ue348\ue349\ue34a\ue34b\ue34c\ue34d\ue34e\ue34f\ue350\ue351\ue352\ue353\ue354\ue355\ue356\ue357\ue358\ue359\ue35a\ue35b\ue35c\ue35d\ue35e\ue35f\ue360\ue361\ue362\ue363\ue364\ue365\ue366\ue367\ue368\ue369\ue36a\ue36b\ue36c\ue36d\ue36e\ue36f\ue370\ue371\ue372\ue373\ue374\ue375\ue376\ue377\ue378\ue379\ue37a\ue37b\ue37c\ue37d\ue37e\ue37f\ue380\ue381\ue382\ue383\ue384\ue385\ue386\ue387\ue388\ue389\ue38a\ue38b\ue38c\ue38d\ue38e\ue38f\ue390\ue391\ue392\ue393\ue394\ue395\ue396\ue397\ue398\ue399\ue39a\ue39b\ue39c\ue39d\ue39e\ue39f\ue3a0\ue3a1\ue3a2\ue3a3\ue3a4\ue3a5\ue3a6\ue3a7\ue3a8\ue3a9\ue3aa\ue3ab\ue3ac\ue3ad\ue3ae\ue3af\ue3b0\ue3b1\ue3b2\ue3b3\ue3b4\ue3b5\ue3b6\ue3b7\ue3b8\ue3b9\ue3ba\ue3bb\ue3bc\ue3bd\ue3be\ue3bf\ue3c0\ue3c1\ue3c2\ue3c3\ue3c4\ue3c5\ue3c6\ue3c7\ue3c8\ue3c9\ue3ca\ue3cb\ue3cc\ue3cd\ue3ce\ue3cf\ue3d0\ue3d1\ue3d2\ue3d3\ue3d4\ue3d5\ue3d6\ue3d7\ue3d8\ue3d9\ue3da\ue3db\ue3dc\ue3dd\ue3de\ue3df\ue3e0\ue3e1\ue3e2\ue3e3\ue3e4\ue3e5\ue3e6\ue3e7\ue3e8\ue3e9\ue3ea\ue3eb\ue3ec\ue3ed\ue3ee\ue3ef\ue3f0\ue3f1\ue3f2\ue3f3\ue3f4\ue3f5\ue3f6\ue3f7\ue3f8\ue3f9\ue3fa\ue3fb\ue3fc\ue3fd\ue3fe\ue3ff\ue400\ue401\ue402\ue403\ue404\ue405\ue406\ue407\ue408\ue409\ue40a\ue40b\ue40c\ue40d\ue40e\ue40f\ue410\ue411\ue412\ue413\ue414\ue415\ue416\ue417\ue418\ue419\ue41a\ue41b\ue41c\ue41d\ue41e\ue41f\ue420\ue421\ue422\ue423\ue424\ue425\ue426\ue427\ue428\ue429\ue42a\ue42b\ue42c\ue42d\ue42e\ue42f\ue430\ue431\ue432\ue433\ue434\ue435\ue436\ue437\ue438\ue439\ue43a\ue43b\ue43c\ue43d\ue43e\ue43f\ue440\ue441\ue442\ue443\ue444\ue445\ue446\ue447\ue448\ue449\ue44a\ue44b\ue44c\ue44d\ue44e\ue44f\ue450\ue451\ue452\ue453\ue454\ue455\ue456\ue457\ue458\ue459\ue45a\ue45b\ue45c\ue45d\ue45e\ue45f\ue460\ue461\ue462\ue463\ue464\ue465\ue466\ue467\ue468\ue469\ue46a\ue46b\ue46c\ue46d\ue46e\ue46f\ue470\ue471\ue472\ue473\ue474\ue475\ue476\ue477\ue478\ue479\ue47a\ue47b\ue47c\ue47d\ue47e\ue47f\ue480\ue481\ue482\ue483\ue484\ue485\ue486\ue487\ue488\ue489\ue48a\ue48b\ue48c\ue48d\ue48e\ue48f\ue490\ue491\ue492\ue493\ue494\ue495\ue496\ue497\ue498\ue499\ue49a\ue49b\ue49c\ue49d\ue49e\ue49f\ue4a0\ue4a1\ue4a2\ue4a3\ue4a4\ue4a5\ue4a6\ue4a7\ue4a8\ue4a9\ue4aa\ue4ab\ue4ac\ue4ad\ue4ae\ue4af\ue4b0\ue4b1\ue4b2\ue4b3\ue4b4\ue4b5\ue4b6\ue4b7\ue4b8\ue4b9\ue4ba\ue4bb\ue4bc\ue4bd\ue4be\ue4bf\ue4c0\ue4c1\ue4c2\ue4c3\ue4c4\ue4c5\ue4c6\ue4c7\ue4c8\ue4c9\ue4ca\ue4cb\ue4cc\ue4cd\ue4ce\ue4cf\ue4d0\ue4d1\ue4d2\ue4d3\ue4d4\ue4d5\ue4d6\ue4d7\ue4d8\ue4d9\ue4da\ue4db\ue4dc\ue4dd\ue4de\ue4df\ue4e0\ue4e1\ue4e2\ue4e3\ue4e4\ue4e5\ue4e6\ue4e7\ue4e8\ue4e9\ue4ea\ue4eb\ue4ec\ue4ed\ue4ee\ue4ef\ue4f0\ue4f1\ue4f2\ue4f3\ue4f4\ue4f5\ue4f6\ue4f7\ue4f8\ue4f9\ue4fa\ue4fb\ue4fc\ue4fd\ue4fe\ue4ff\ue500\ue501\ue502\ue503\ue504\ue505\ue506\ue507\ue508\ue509\ue50a\ue50b\ue50c\ue50d\ue50e\ue50f\ue510\ue511\ue512\ue513\ue514\ue515\ue516\ue517\ue518\ue519\ue51a\ue51b\ue51c\ue51d\ue51e\ue51f\ue520\ue521\ue522\ue523\ue524\ue525\ue526\ue527\ue528\ue529\ue52a\ue52b\ue52c\ue52d\ue52e\ue52f\ue530\ue531\ue532\ue533\ue534\ue535\ue536\ue537\ue538\ue539\ue53a\ue53b\ue53c\ue53d\ue53e\ue53f\ue540\ue541\ue542\ue543\ue544\ue545\ue546\ue547\ue548\ue549\ue54a\ue54b\ue54c\ue54d\ue54e\ue54f\ue550\ue551\ue552\ue553\ue554\ue555\ue556\ue557\ue558\ue559\ue55a\ue55b\ue55c\ue55d\ue55e\ue55f\ue560\ue561\ue562\ue563\ue564\ue565\ue566\ue567\ue568\ue569\ue56a\ue56b\ue56c\ue56d\ue56e\ue56f\ue570\ue571\ue572\ue573\ue574\ue575\ue576\ue577\ue578\ue579\ue57a\ue57b\ue57c\ue57d\ue57e\ue57f\ue580\ue581\ue582\ue583\ue584\ue585\ue586\ue587\ue588\ue589\ue58a\ue58b\ue58c\ue58d\ue58e\ue58f\ue590\ue591\ue592\ue593\ue594\ue595\ue596\ue597\ue598\ue599\ue59a\ue59b\ue59c\ue59d\ue59e\ue59f\ue5a0\ue5a1\ue5a2\ue5a3\ue5a4\ue5a5\ue5a6\ue5a7\ue5a8\ue5a9\ue5aa\ue5ab\ue5ac\ue5ad\ue5ae\ue5af\ue5b0\ue5b1\ue5b2\ue5b3\ue5b4\ue5b5\ue5b6\ue5b7\ue5b8\ue5b9\ue5ba\ue5bb\ue5bc\ue5bd\ue5be\ue5bf\ue5c0\ue5c1\ue5c2\ue5c3\ue5c4\ue5c5\ue5c6\ue5c7\ue5c8\ue5c9\ue5ca\ue5cb\ue5cc\ue5cd\ue5ce\ue5cf\ue5d0\ue5d1\ue5d2\ue5d3\ue5d4\ue5d5\ue5d6\ue5d7\ue5d8\ue5d9\ue5da\ue5db\ue5dc\ue5dd\ue5de\ue5df\ue5e0\ue5e1\ue5e2\ue5e3\ue5e4\ue5e5\ue5e6\ue5e7\ue5e8\ue5e9\ue5ea\ue5eb\ue5ec\ue5ed\ue5ee\ue5ef\ue5f0\ue5f1\ue5f2\ue5f3\ue5f4\ue5f5\ue5f6\ue5f7\ue5f8\ue5f9\ue5fa\ue5fb\ue5fc\ue5fd\ue5fe\ue5ff\ue600\ue601\ue602\ue603\ue604\ue605\ue606\ue607\ue608\ue609\ue60a\ue60b\ue60c\ue60d\ue60e\ue60f\ue610\ue611\ue612\ue613\ue614\ue615\ue616\ue617\ue618\ue619\ue61a\ue61b\ue61c\ue61d\ue61e\ue61f\ue620\ue621\ue622\ue623\ue624\ue625\ue626\ue627\ue628\ue629\ue62a\ue62b\ue62c\ue62d\ue62e\ue62f\ue630\ue631\ue632\ue633\ue634\ue635\ue636\ue637\ue638\ue639\ue63a\ue63b\ue63c\ue63d\ue63e\ue63f\ue640\ue641\ue642\ue643\ue644\ue645\ue646\ue647\ue648\ue649\ue64a\ue64b\ue64c\ue64d\ue64e\ue64f\ue650\ue651\ue652\ue653\ue654\ue655\ue656\ue657\ue658\ue659\ue65a\ue65b\ue65c\ue65d\ue65e\ue65f\ue660\ue661\ue662\ue663\ue664\ue665\ue666\ue667\ue668\ue669\ue66a\ue66b\ue66c\ue66d\ue66e\ue66f\ue670\ue671\ue672\ue673\ue674\ue675\ue676\ue677\ue678\ue679\ue67a\ue67b\ue67c\ue67d\ue67e\ue67f\ue680\ue681\ue682\ue683\ue684\ue685\ue686\ue687\ue688\ue689\ue68a\ue68b\ue68c\ue68d\ue68e\ue68f\ue690\ue691\ue692\ue693\ue694\ue695\ue696\ue697\ue698\ue699\ue69a\ue69b\ue69c\ue69d\ue69e\ue69f\ue6a0\ue6a1\ue6a2\ue6a3\ue6a4\ue6a5\ue6a6\ue6a7\ue6a8\ue6a9\ue6aa\ue6ab\ue6ac\ue6ad\ue6ae\ue6af\ue6b0\ue6b1\ue6b2\ue6b3\ue6b4\ue6b5\ue6b6\ue6b7\ue6b8\ue6b9\ue6ba\ue6bb\ue6bc\ue6bd\ue6be\ue6bf\ue6c0\ue6c1\ue6c2\ue6c3\ue6c4\ue6c5\ue6c6\ue6c7\ue6c8\ue6c9\ue6ca\ue6cb\ue6cc\ue6cd\ue6ce\ue6cf\ue6d0\ue6d1\ue6d2\ue6d3\ue6d4\ue6d5\ue6d6\ue6d7\ue6d8\ue6d9\ue6da\ue6db\ue6dc\ue6dd\ue6de\ue6df\ue6e0\ue6e1\ue6e2\ue6e3\ue6e4\ue6e5\ue6e6\ue6e7\ue6e8\ue6e9\ue6ea\ue6eb\ue6ec\ue6ed\ue6ee\ue6ef\ue6f0\ue6f1\ue6f2\ue6f3\ue6f4\ue6f5\ue6f6\ue6f7\ue6f8\ue6f9\ue6fa\ue6fb\ue6fc\ue6fd\ue6fe\ue6ff\ue700\ue701\ue702\ue703\ue704\ue705\ue706\ue707\ue708\ue709\ue70a\ue70b\ue70c\ue70d\ue70e\ue70f\ue710\ue711\ue712\ue713\ue714\ue715\ue716\ue717\ue718\ue719\ue71a\ue71b\ue71c\ue71d\ue71e\ue71f\ue720\ue721\ue722\ue723\ue724\ue725\ue726\ue727\ue728\ue729\ue72a\ue72b\ue72c\ue72d\ue72e\ue72f\ue730\ue731\ue732\ue733\ue734\ue735\ue736\ue737\ue738\ue739\ue73a\ue73b\ue73c\ue73d\ue73e\ue73f\ue740\ue741\ue742\ue743\ue744\ue745\ue746\ue747\ue748\ue749\ue74a\ue74b\ue74c\ue74d\ue74e\ue74f\ue750\ue751\ue752\ue753\ue754\ue755\ue756\ue757\ue758\ue759\ue75a\ue75b\ue75c\ue75d\ue75e\ue75f\ue760\ue761\ue762\ue763\ue764\ue765\ue766\ue767\ue768\ue769\ue76a\ue76b\ue76c\ue76d\ue76e\ue76f\ue770\ue771\ue772\ue773\ue774\ue775\ue776\ue777\ue778\ue779\ue77a\ue77b\ue77c\ue77d\ue77e\ue77f\ue780\ue781\ue782\ue783\ue784\ue785\ue786\ue787\ue788\ue789\ue78a\ue78b\ue78c\ue78d\ue78e\ue78f\ue790\ue791\ue792\ue793\ue794\ue795\ue796\ue797\ue798\ue799\ue79a\ue79b\ue79c\ue79d\ue79e\ue79f\ue7a0\ue7a1\ue7a2\ue7a3\ue7a4\ue7a5\ue7a6\ue7a7\ue7a8\ue7a9\ue7aa\ue7ab\ue7ac\ue7ad\ue7ae\ue7af\ue7b0\ue7b1\ue7b2\ue7b3\ue7b4\ue7b5\ue7b6\ue7b7\ue7b8\ue7b9\ue7ba\ue7bb\ue7bc\ue7bd\ue7be\ue7bf\ue7c0\ue7c1\ue7c2\ue7c3\ue7c4\ue7c5\ue7c6\ue7c7\ue7c8\ue7c9\ue7ca\ue7cb\ue7cc\ue7cd\ue7ce\ue7cf\ue7d0\ue7d1\ue7d2\ue7d3\ue7d4\ue7d5\ue7d6\ue7d7\ue7d8\ue7d9\ue7da\ue7db\ue7dc\ue7dd\ue7de\ue7df\ue7e0\ue7e1\ue7e2\ue7e3\ue7e4\ue7e5\ue7e6\ue7e7\ue7e8\ue7e9\ue7ea\ue7eb\ue7ec\ue7ed\ue7ee\ue7ef\ue7f0\ue7f1\ue7f2\ue7f3\ue7f4\ue7f5\ue7f6\ue7f7\ue7f8\ue7f9\ue7fa\ue7fb\ue7fc\ue7fd\ue7fe\ue7ff\ue800\ue801\ue802\ue803\ue804\ue805\ue806\ue807\ue808\ue809\ue80a\ue80b\ue80c\ue80d\ue80e\ue80f\ue810\ue811\ue812\ue813\ue814\ue815\ue816\ue817\ue818\ue819\ue81a\ue81b\ue81c\ue81d\ue81e\ue81f\ue820\ue821\ue822\ue823\ue824\ue825\ue826\ue827\ue828\ue829\ue82a\ue82b\ue82c\ue82d\ue82e\ue82f\ue830\ue831\ue832\ue833\ue834\ue835\ue836\ue837\ue838\ue839\ue83a\ue83b\ue83c\ue83d\ue83e\ue83f\ue840\ue841\ue842\ue843\ue844\ue845\ue846\ue847\ue848\ue849\ue84a\ue84b\ue84c\ue84d\ue84e\ue84f\ue850\ue851\ue852\ue853\ue854\ue855\ue856\ue857\ue858\ue859\ue85a\ue85b\ue85c\ue85d\ue85e\ue85f\ue860\ue861\ue862\ue863\ue864\ue865\ue866\ue867\ue868\ue869\ue86a\ue86b\ue86c\ue86d\ue86e\ue86f\ue870\ue871\ue872\ue873\ue874\ue875\ue876\ue877\ue878\ue879\ue87a\ue87b\ue87c\ue87d\ue87e\ue87f\ue880\ue881\ue882\ue883\ue884\ue885\ue886\ue887\ue888\ue889\ue88a\ue88b\ue88c\ue88d\ue88e\ue88f\ue890\ue891\ue892\ue893\ue894\ue895\ue896\ue897\ue898\ue899\ue89a\ue89b\ue89c\ue89d\ue89e\ue89f\ue8a0\ue8a1\ue8a2\ue8a3\ue8a4\ue8a5\ue8a6\ue8a7\ue8a8\ue8a9\ue8aa\ue8ab\ue8ac\ue8ad\ue8ae\ue8af\ue8b0\ue8b1\ue8b2\ue8b3\ue8b4\ue8b5\ue8b6\ue8b7\ue8b8\ue8b9\ue8ba\ue8bb\ue8bc\ue8bd\ue8be\ue8bf\ue8c0\ue8c1\ue8c2\ue8c3\ue8c4\ue8c5\ue8c6\ue8c7\ue8c8\ue8c9\ue8ca\ue8cb\ue8cc\ue8cd\ue8ce\ue8cf\ue8d0\ue8d1\ue8d2\ue8d3\ue8d4\ue8d5\ue8d6\ue8d7\ue8d8\ue8d9\ue8da\ue8db\ue8dc\ue8dd\ue8de\ue8df\ue8e0\ue8e1\ue8e2\ue8e3\ue8e4\ue8e5\ue8e6\ue8e7\ue8e8\ue8e9\ue8ea\ue8eb\ue8ec\ue8ed\ue8ee\ue8ef\ue8f0\ue8f1\ue8f2\ue8f3\ue8f4\ue8f5\ue8f6\ue8f7\ue8f8\ue8f9\ue8fa\ue8fb\ue8fc\ue8fd\ue8fe\ue8ff\ue900\ue901\ue902\ue903\ue904\ue905\ue906\ue907\ue908\ue909\ue90a\ue90b\ue90c\ue90d\ue90e\ue90f\ue910\ue911\ue912\ue913\ue914\ue915\ue916\ue917\ue918\ue919\ue91a\ue91b\ue91c\ue91d\ue91e\ue91f\ue920\ue921\ue922\ue923\ue924\ue925\ue926\ue927\ue928\ue929\ue92a\ue92b\ue92c\ue92d\ue92e\ue92f\ue930\ue931\ue932\ue933\ue934\ue935\ue936\ue937\ue938\ue939\ue93a\ue93b\ue93c\ue93d\ue93e\ue93f\ue940\ue941\ue942\ue943\ue944\ue945\ue946\ue947\ue948\ue949\ue94a\ue94b\ue94c\ue94d\ue94e\ue94f\ue950\ue951\ue952\ue953\ue954\ue955\ue956\ue957\ue958\ue959\ue95a\ue95b\ue95c\ue95d\ue95e\ue95f\ue960\ue961\ue962\ue963\ue964\ue965\ue966\ue967\ue968\ue969\ue96a\ue96b\ue96c\ue96d\ue96e\ue96f\ue970\ue971\ue972\ue973\ue974\ue975\ue976\ue977\ue978\ue979\ue97a\ue97b\ue97c\ue97d\ue97e\ue97f\ue980\ue981\ue982\ue983\ue984\ue985\ue986\ue987\ue988\ue989\ue98a\ue98b\ue98c\ue98d\ue98e\ue98f\ue990\ue991\ue992\ue993\ue994\ue995\ue996\ue997\ue998\ue999\ue99a\ue99b\ue99c\ue99d\ue99e\ue99f\ue9a0\ue9a1\ue9a2\ue9a3\ue9a4\ue9a5\ue9a6\ue9a7\ue9a8\ue9a9\ue9aa\ue9ab\ue9ac\ue9ad\ue9ae\ue9af\ue9b0\ue9b1\ue9b2\ue9b3\ue9b4\ue9b5\ue9b6\ue9b7\ue9b8\ue9b9\ue9ba\ue9bb\ue9bc\ue9bd\ue9be\ue9bf\ue9c0\ue9c1\ue9c2\ue9c3\ue9c4\ue9c5\ue9c6\ue9c7\ue9c8\ue9c9\ue9ca\ue9cb\ue9cc\ue9cd\ue9ce\ue9cf\ue9d0\ue9d1\ue9d2\ue9d3\ue9d4\ue9d5\ue9d6\ue9d7\ue9d8\ue9d9\ue9da\ue9db\ue9dc\ue9dd\ue9de\ue9df\ue9e0\ue9e1\ue9e2\ue9e3\ue9e4\ue9e5\ue9e6\ue9e7\ue9e8\ue9e9\ue9ea\ue9eb\ue9ec\ue9ed\ue9ee\ue9ef\ue9f0\ue9f1\ue9f2\ue9f3\ue9f4\ue9f5\ue9f6\ue9f7\ue9f8\ue9f9\ue9fa\ue9fb\ue9fc\ue9fd\ue9fe\ue9ff\uea00\uea01\uea02\uea03\uea04\uea05\uea06\uea07\uea08\uea09\uea0a\uea0b\uea0c\uea0d\uea0e\uea0f\uea10\uea11\uea12\uea13\uea14\uea15\uea16\uea17\uea18\uea19\uea1a\uea1b\uea1c\uea1d\uea1e\uea1f\uea20\uea21\uea22\uea23\uea24\uea25\uea26\uea27\uea28\uea29\uea2a\uea2b\uea2c\uea2d\uea2e\uea2f\uea30\uea31\uea32\uea33\uea34\uea35\uea36\uea37\uea38\uea39\uea3a\uea3b\uea3c\uea3d\uea3e\uea3f\uea40\uea41\uea42\uea43\uea44\uea45\uea46\uea47\uea48\uea49\uea4a\uea4b\uea4c\uea4d\uea4e\uea4f\uea50\uea51\uea52\uea53\uea54\uea55\uea56\uea57\uea58\uea59\uea5a\uea5b\uea5c\uea5d\uea5e\uea5f\uea60\uea61\uea62\uea63\uea64\uea65\uea66\uea67\uea68\uea69\uea6a\uea6b\uea6c\uea6d\uea6e\uea6f\uea70\uea71\uea72\uea73\uea74\uea75\uea76\uea77\uea78\uea79\uea7a\uea7b\uea7c\uea7d\uea7e\uea7f\uea80\uea81\uea82\uea83\uea84\uea85\uea86\uea87\uea88\uea89\uea8a\uea8b\uea8c\uea8d\uea8e\uea8f\uea90\uea91\uea92\uea93\uea94\uea95\uea96\uea97\uea98\uea99\uea9a\uea9b\uea9c\uea9d\uea9e\uea9f\ueaa0\ueaa1\ueaa2\ueaa3\ueaa4\ueaa5\ueaa6\ueaa7\ueaa8\ueaa9\ueaaa\ueaab\ueaac\ueaad\ueaae\ueaaf\ueab0\ueab1\ueab2\ueab3\ueab4\ueab5\ueab6\ueab7\ueab8\ueab9\ueaba\ueabb\ueabc\ueabd\ueabe\ueabf\ueac0\ueac1\ueac2\ueac3\ueac4\ueac5\ueac6\ueac7\ueac8\ueac9\ueaca\ueacb\ueacc\ueacd\ueace\ueacf\uead0\uead1\uead2\uead3\uead4\uead5\uead6\uead7\uead8\uead9\ueada\ueadb\ueadc\ueadd\ueade\ueadf\ueae0\ueae1\ueae2\ueae3\ueae4\ueae5\ueae6\ueae7\ueae8\ueae9\ueaea\ueaeb\ueaec\ueaed\ueaee\ueaef\ueaf0\ueaf1\ueaf2\ueaf3\ueaf4\ueaf5\ueaf6\ueaf7\ueaf8\ueaf9\ueafa\ueafb\ueafc\ueafd\ueafe\ueaff\ueb00\ueb01\ueb02\ueb03\ueb04\ueb05\ueb06\ueb07\ueb08\ueb09\ueb0a\ueb0b\ueb0c\ueb0d\ueb0e\ueb0f\ueb10\ueb11\ueb12\ueb13\ueb14\ueb15\ueb16\ueb17\ueb18\ueb19\ueb1a\ueb1b\ueb1c\ueb1d\ueb1e\ueb1f\ueb20\ueb21\ueb22\ueb23\ueb24\ueb25\ueb26\ueb27\ueb28\ueb29\ueb2a\ueb2b\ueb2c\ueb2d\ueb2e\ueb2f\ueb30\ueb31\ueb32\ueb33\ueb34\ueb35\ueb36\ueb37\ueb38\ueb39\ueb3a\ueb3b\ueb3c\ueb3d\ueb3e\ueb3f\ueb40\ueb41\ueb42\ueb43\ueb44\ueb45\ueb46\ueb47\ueb48\ueb49\ueb4a\ueb4b\ueb4c\ueb4d\ueb4e\ueb4f\ueb50\ueb51\ueb52\ueb53\ueb54\ueb55\ueb56\ueb57\ueb58\ueb59\ueb5a\ueb5b\ueb5c\ueb5d\ueb5e\ueb5f\ueb60\ueb61\ueb62\ueb63\ueb64\ueb65\ueb66\ueb67\ueb68\ueb69\ueb6a\ueb6b\ueb6c\ueb6d\ueb6e\ueb6f\ueb70\ueb71\ueb72\ueb73\ueb74\ueb75\ueb76\ueb77\ueb78\ueb79\ueb7a\ueb7b\ueb7c\ueb7d\ueb7e\ueb7f\ueb80\ueb81\ueb82\ueb83\ueb84\ueb85\ueb86\ueb87\ueb88\ueb89\ueb8a\ueb8b\ueb8c\ueb8d\ueb8e\ueb8f\ueb90\ueb91\ueb92\ueb93\ueb94\ueb95\ueb96\ueb97\ueb98\ueb99\ueb9a\ueb9b\ueb9c\ueb9d\ueb9e\ueb9f\ueba0\ueba1\ueba2\ueba3\ueba4\ueba5\ueba6\ueba7\ueba8\ueba9\uebaa\uebab\uebac\uebad\uebae\uebaf\uebb0\uebb1\uebb2\uebb3\uebb4\uebb5\uebb6\uebb7\uebb8\uebb9\uebba\uebbb\uebbc\uebbd\uebbe\uebbf\uebc0\uebc1\uebc2\uebc3\uebc4\uebc5\uebc6\uebc7\uebc8\uebc9\uebca\uebcb\uebcc\uebcd\uebce\uebcf\uebd0\uebd1\uebd2\uebd3\uebd4\uebd5\uebd6\uebd7\uebd8\uebd9\uebda\uebdb\uebdc\uebdd\uebde\uebdf\uebe0\uebe1\uebe2\uebe3\uebe4\uebe5\uebe6\uebe7\uebe8\uebe9\uebea\uebeb\uebec\uebed\uebee\uebef\uebf0\uebf1\uebf2\uebf3\uebf4\uebf5\uebf6\uebf7\uebf8\uebf9\uebfa\uebfb\uebfc\uebfd\uebfe\uebff\uec00\uec01\uec02\uec03\uec04\uec05\uec06\uec07\uec08\uec09\uec0a\uec0b\uec0c\uec0d\uec0e\uec0f\uec10\uec11\uec12\uec13\uec14\uec15\uec16\uec17\uec18\uec19\uec1a\uec1b\uec1c\uec1d\uec1e\uec1f\uec20\uec21\uec22\uec23\uec24\uec25\uec26\uec27\uec28\uec29\uec2a\uec2b\uec2c\uec2d\uec2e\uec2f\uec30\uec31\uec32\uec33\uec34\uec35\uec36\uec37\uec38\uec39\uec3a\uec3b\uec3c\uec3d\uec3e\uec3f\uec40\uec41\uec42\uec43\uec44\uec45\uec46\uec47\uec48\uec49\uec4a\uec4b\uec4c\uec4d\uec4e\uec4f\uec50\uec51\uec52\uec53\uec54\uec55\uec56\uec57\uec58\uec59\uec5a\uec5b\uec5c\uec5d\uec5e\uec5f\uec60\uec61\uec62\uec63\uec64\uec65\uec66\uec67\uec68\uec69\uec6a\uec6b\uec6c\uec6d\uec6e\uec6f\uec70\uec71\uec72\uec73\uec74\uec75\uec76\uec77\uec78\uec79\uec7a\uec7b\uec7c\uec7d\uec7e\uec7f\uec80\uec81\uec82\uec83\uec84\uec85\uec86\uec87\uec88\uec89\uec8a\uec8b\uec8c\uec8d\uec8e\uec8f\uec90\uec91\uec92\uec93\uec94\uec95\uec96\uec97\uec98\uec99\uec9a\uec9b\uec9c\uec9d\uec9e\uec9f\ueca0\ueca1\ueca2\ueca3\ueca4\ueca5\ueca6\ueca7\ueca8\ueca9\uecaa\uecab\uecac\uecad\uecae\uecaf\uecb0\uecb1\uecb2\uecb3\uecb4\uecb5\uecb6\uecb7\uecb8\uecb9\uecba\uecbb\uecbc\uecbd\uecbe\uecbf\uecc0\uecc1\uecc2\uecc3\uecc4\uecc5\uecc6\uecc7\uecc8\uecc9\uecca\ueccb\ueccc\ueccd\uecce\ueccf\uecd0\uecd1\uecd2\uecd3\uecd4\uecd5\uecd6\uecd7\uecd8\uecd9\uecda\uecdb\uecdc\uecdd\uecde\uecdf\uece0\uece1\uece2\uece3\uece4\uece5\uece6\uece7\uece8\uece9\uecea\ueceb\uecec\ueced\uecee\uecef\uecf0\uecf1\uecf2\uecf3\uecf4\uecf5\uecf6\uecf7\uecf8\uecf9\uecfa\uecfb\uecfc\uecfd\uecfe\uecff\ued00\ued01\ued02\ued03\ued04\ued05\ued06\ued07\ued08\ued09\ued0a\ued0b\ued0c\ued0d\ued0e\ued0f\ued10\ued11\ued12\ued13\ued14\ued15\ued16\ued17\ued18\ued19\ued1a\ued1b\ued1c\ued1d\ued1e\ued1f\ued20\ued21\ued22\ued23\ued24\ued25\ued26\ued27\ued28\ued29\ued2a\ued2b\ued2c\ued2d\ued2e\ued2f\ued30\ued31\ued32\ued33\ued34\ued35\ued36\ued37\ued38\ued39\ued3a\ued3b\ued3c\ued3d\ued3e\ued3f\ued40\ued41\ued42\ued43\ued44\ued45\ued46\ued47\ued48\ued49\ued4a\ued4b\ued4c\ued4d\ued4e\ued4f\ued50\ued51\ued52\ued53\ued54\ued55\ued56\ued57\ued58\ued59\ued5a\ued5b\ued5c\ued5d\ued5e\ued5f\ued60\ued61\ued62\ued63\ued64\ued65\ued66\ued67\ued68\ued69\ued6a\ued6b\ued6c\ued6d\ued6e\ued6f\ued70\ued71\ued72\ued73\ued74\ued75\ued76\ued77\ued78\ued79\ued7a\ued7b\ued7c\ued7d\ued7e\ued7f\ued80\ued81\ued82\ued83\ued84\ued85\ued86\ued87\ued88\ued89\ued8a\ued8b\ued8c\ued8d\ued8e\ued8f\ued90\ued91\ued92\ued93\ued94\ued95\ued96\ued97\ued98\ued99\ued9a\ued9b\ued9c\ued9d\ued9e\ued9f\ueda0\ueda1\ueda2\ueda3\ueda4\ueda5\ueda6\ueda7\ueda8\ueda9\uedaa\uedab\uedac\uedad\uedae\uedaf\uedb0\uedb1\uedb2\uedb3\uedb4\uedb5\uedb6\uedb7\uedb8\uedb9\uedba\uedbb\uedbc\uedbd\uedbe\uedbf\uedc0\uedc1\uedc2\uedc3\uedc4\uedc5\uedc6\uedc7\uedc8\uedc9\uedca\uedcb\uedcc\uedcd\uedce\uedcf\uedd0\uedd1\uedd2\uedd3\uedd4\uedd5\uedd6\uedd7\uedd8\uedd9\uedda\ueddb\ueddc\ueddd\uedde\ueddf\uede0\uede1\uede2\uede3\uede4\uede5\uede6\uede7\uede8\uede9\uedea\uedeb\uedec\ueded\uedee\uedef\uedf0\uedf1\uedf2\uedf3\uedf4\uedf5\uedf6\uedf7\uedf8\uedf9\uedfa\uedfb\uedfc\uedfd\uedfe\uedff\uee00\uee01\uee02\uee03\uee04\uee05\uee06\uee07\uee08\uee09\uee0a\uee0b\uee0c\uee0d\uee0e\uee0f\uee10\uee11\uee12\uee13\uee14\uee15\uee16\uee17\uee18\uee19\uee1a\uee1b\uee1c\uee1d\uee1e\uee1f\uee20\uee21\uee22\uee23\uee24\uee25\uee26\uee27\uee28\uee29\uee2a\uee2b\uee2c\uee2d\uee2e\uee2f\uee30\uee31\uee32\uee33\uee34\uee35\uee36\uee37\uee38\uee39\uee3a\uee3b\uee3c\uee3d\uee3e\uee3f\uee40\uee41\uee42\uee43\uee44\uee45\uee46\uee47\uee48\uee49\uee4a\uee4b\uee4c\uee4d\uee4e\uee4f\uee50\uee51\uee52\uee53\uee54\uee55\uee56\uee57\uee58\uee59\uee5a\uee5b\uee5c\uee5d\uee5e\uee5f\uee60\uee61\uee62\uee63\uee64\uee65\uee66\uee67\uee68\uee69\uee6a\uee6b\uee6c\uee6d\uee6e\uee6f\uee70\uee71\uee72\uee73\uee74\uee75\uee76\uee77\uee78\uee79\uee7a\uee7b\uee7c\uee7d\uee7e\uee7f\uee80\uee81\uee82\uee83\uee84\uee85\uee86\uee87\uee88\uee89\uee8a\uee8b\uee8c\uee8d\uee8e\uee8f\uee90\uee91\uee92\uee93\uee94\uee95\uee96\uee97\uee98\uee99\uee9a\uee9b\uee9c\uee9d\uee9e\uee9f\ueea0\ueea1\ueea2\ueea3\ueea4\ueea5\ueea6\ueea7\ueea8\ueea9\ueeaa\ueeab\ueeac\ueead\ueeae\ueeaf\ueeb0\ueeb1\ueeb2\ueeb3\ueeb4\ueeb5\ueeb6\ueeb7\ueeb8\ueeb9\ueeba\ueebb\ueebc\ueebd\ueebe\ueebf\ueec0\ueec1\ueec2\ueec3\ueec4\ueec5\ueec6\ueec7\ueec8\ueec9\ueeca\ueecb\ueecc\ueecd\ueece\ueecf\ueed0\ueed1\ueed2\ueed3\ueed4\ueed5\ueed6\ueed7\ueed8\ueed9\ueeda\ueedb\ueedc\ueedd\ueede\ueedf\ueee0\ueee1\ueee2\ueee3\ueee4\ueee5\ueee6\ueee7\ueee8\ueee9\ueeea\ueeeb\ueeec\ueeed\ueeee\ueeef\ueef0\ueef1\ueef2\ueef3\ueef4\ueef5\ueef6\ueef7\ueef8\ueef9\ueefa\ueefb\ueefc\ueefd\ueefe\ueeff\uef00\uef01\uef02\uef03\uef04\uef05\uef06\uef07\uef08\uef09\uef0a\uef0b\uef0c\uef0d\uef0e\uef0f\uef10\uef11\uef12\uef13\uef14\uef15\uef16\uef17\uef18\uef19\uef1a\uef1b\uef1c\uef1d\uef1e\uef1f\uef20\uef21\uef22\uef23\uef24\uef25\uef26\uef27\uef28\uef29\uef2a\uef2b\uef2c\uef2d\uef2e\uef2f\uef30\uef31\uef32\uef33\uef34\uef35\uef36\uef37\uef38\uef39\uef3a\uef3b\uef3c\uef3d\uef3e\uef3f\uef40\uef41\uef42\uef43\uef44\uef45\uef46\uef47\uef48\uef49\uef4a\uef4b\uef4c\uef4d\uef4e\uef4f\uef50\uef51\uef52\uef53\uef54\uef55\uef56\uef57\uef58\uef59\uef5a\uef5b\uef5c\uef5d\uef5e\uef5f\uef60\uef61\uef62\uef63\uef64\uef65\uef66\uef67\uef68\uef69\uef6a\uef6b\uef6c\uef6d\uef6e\uef6f\uef70\uef71\uef72\uef73\uef74\uef75\uef76\uef77\uef78\uef79\uef7a\uef7b\uef7c\uef7d\uef7e\uef7f\uef80\uef81\uef82\uef83\uef84\uef85\uef86\uef87\uef88\uef89\uef8a\uef8b\uef8c\uef8d\uef8e\uef8f\uef90\uef91\uef92\uef93\uef94\uef95\uef96\uef97\uef98\uef99\uef9a\uef9b\uef9c\uef9d\uef9e\uef9f\uefa0\uefa1\uefa2\uefa3\uefa4\uefa5\uefa6\uefa7\uefa8\uefa9\uefaa\uefab\uefac\uefad\uefae\uefaf\uefb0\uefb1\uefb2\uefb3\uefb4\uefb5\uefb6\uefb7\uefb8\uefb9\uefba\uefbb\uefbc\uefbd\uefbe\uefbf\uefc0\uefc1\uefc2\uefc3\uefc4\uefc5\uefc6\uefc7\uefc8\uefc9\uefca\uefcb\uefcc\uefcd\uefce\uefcf\uefd0\uefd1\uefd2\uefd3\uefd4\uefd5\uefd6\uefd7\uefd8\uefd9\uefda\uefdb\uefdc\uefdd\uefde\uefdf\uefe0\uefe1\uefe2\uefe3\uefe4\uefe5\uefe6\uefe7\uefe8\uefe9\uefea\uefeb\uefec\uefed\uefee\uefef\ueff0\ueff1\ueff2\ueff3\ueff4\ueff5\ueff6\ueff7\ueff8\ueff9\ueffa\ueffb\ueffc\ueffd\ueffe\uefff\uf000\uf001\uf002\uf003\uf004\uf005\uf006\uf007\uf008\uf009\uf00a\uf00b\uf00c\uf00d\uf00e\uf00f\uf010\uf011\uf012\uf013\uf014\uf015\uf016\uf017\uf018\uf019\uf01a\uf01b\uf01c\uf01d\uf01e\uf01f\uf020\uf021\uf022\uf023\uf024\uf025\uf026\uf027\uf028\uf029\uf02a\uf02b\uf02c\uf02d\uf02e\uf02f\uf030\uf031\uf032\uf033\uf034\uf035\uf036\uf037\uf038\uf039\uf03a\uf03b\uf03c\uf03d\uf03e\uf03f\uf040\uf041\uf042\uf043\uf044\uf045\uf046\uf047\uf048\uf049\uf04a\uf04b\uf04c\uf04d\uf04e\uf04f\uf050\uf051\uf052\uf053\uf054\uf055\uf056\uf057\uf058\uf059\uf05a\uf05b\uf05c\uf05d\uf05e\uf05f\uf060\uf061\uf062\uf063\uf064\uf065\uf066\uf067\uf068\uf069\uf06a\uf06b\uf06c\uf06d\uf06e\uf06f\uf070\uf071\uf072\uf073\uf074\uf075\uf076\uf077\uf078\uf079\uf07a\uf07b\uf07c\uf07d\uf07e\uf07f\uf080\uf081\uf082\uf083\uf084\uf085\uf086\uf087\uf088\uf089\uf08a\uf08b\uf08c\uf08d\uf08e\uf08f\uf090\uf091\uf092\uf093\uf094\uf095\uf096\uf097\uf098\uf099\uf09a\uf09b\uf09c\uf09d\uf09e\uf09f\uf0a0\uf0a1\uf0a2\uf0a3\uf0a4\uf0a5\uf0a6\uf0a7\uf0a8\uf0a9\uf0aa\uf0ab\uf0ac\uf0ad\uf0ae\uf0af\uf0b0\uf0b1\uf0b2\uf0b3\uf0b4\uf0b5\uf0b6\uf0b7\uf0b8\uf0b9\uf0ba\uf0bb\uf0bc\uf0bd\uf0be\uf0bf\uf0c0\uf0c1\uf0c2\uf0c3\uf0c4\uf0c5\uf0c6\uf0c7\uf0c8\uf0c9\uf0ca\uf0cb\uf0cc\uf0cd\uf0ce\uf0cf\uf0d0\uf0d1\uf0d2\uf0d3\uf0d4\uf0d5\uf0d6\uf0d7\uf0d8\uf0d9\uf0da\uf0db\uf0dc\uf0dd\uf0de\uf0df\uf0e0\uf0e1\uf0e2\uf0e3\uf0e4\uf0e5\uf0e6\uf0e7\uf0e8\uf0e9\uf0ea\uf0eb\uf0ec\uf0ed\uf0ee\uf0ef\uf0f0\uf0f1\uf0f2\uf0f3\uf0f4\uf0f5\uf0f6\uf0f7\uf0f8\uf0f9\uf0fa\uf0fb\uf0fc\uf0fd\uf0fe\uf0ff\uf100\uf101\uf102\uf103\uf104\uf105\uf106\uf107\uf108\uf109\uf10a\uf10b\uf10c\uf10d\uf10e\uf10f\uf110\uf111\uf112\uf113\uf114\uf115\uf116\uf117\uf118\uf119\uf11a\uf11b\uf11c\uf11d\uf11e\uf11f\uf120\uf121\uf122\uf123\uf124\uf125\uf126\uf127\uf128\uf129\uf12a\uf12b\uf12c\uf12d\uf12e\uf12f\uf130\uf131\uf132\uf133\uf134\uf135\uf136\uf137\uf138\uf139\uf13a\uf13b\uf13c\uf13d\uf13e\uf13f\uf140\uf141\uf142\uf143\uf144\uf145\uf146\uf147\uf148\uf149\uf14a\uf14b\uf14c\uf14d\uf14e\uf14f\uf150\uf151\uf152\uf153\uf154\uf155\uf156\uf157\uf158\uf159\uf15a\uf15b\uf15c\uf15d\uf15e\uf15f\uf160\uf161\uf162\uf163\uf164\uf165\uf166\uf167\uf168\uf169\uf16a\uf16b\uf16c\uf16d\uf16e\uf16f\uf170\uf171\uf172\uf173\uf174\uf175\uf176\uf177\uf178\uf179\uf17a\uf17b\uf17c\uf17d\uf17e\uf17f\uf180\uf181\uf182\uf183\uf184\uf185\uf186\uf187\uf188\uf189\uf18a\uf18b\uf18c\uf18d\uf18e\uf18f\uf190\uf191\uf192\uf193\uf194\uf195\uf196\uf197\uf198\uf199\uf19a\uf19b\uf19c\uf19d\uf19e\uf19f\uf1a0\uf1a1\uf1a2\uf1a3\uf1a4\uf1a5\uf1a6\uf1a7\uf1a8\uf1a9\uf1aa\uf1ab\uf1ac\uf1ad\uf1ae\uf1af\uf1b0\uf1b1\uf1b2\uf1b3\uf1b4\uf1b5\uf1b6\uf1b7\uf1b8\uf1b9\uf1ba\uf1bb\uf1bc\uf1bd\uf1be\uf1bf\uf1c0\uf1c1\uf1c2\uf1c3\uf1c4\uf1c5\uf1c6\uf1c7\uf1c8\uf1c9\uf1ca\uf1cb\uf1cc\uf1cd\uf1ce\uf1cf\uf1d0\uf1d1\uf1d2\uf1d3\uf1d4\uf1d5\uf1d6\uf1d7\uf1d8\uf1d9\uf1da\uf1db\uf1dc\uf1dd\uf1de\uf1df\uf1e0\uf1e1\uf1e2\uf1e3\uf1e4\uf1e5\uf1e6\uf1e7\uf1e8\uf1e9\uf1ea\uf1eb\uf1ec\uf1ed\uf1ee\uf1ef\uf1f0\uf1f1\uf1f2\uf1f3\uf1f4\uf1f5\uf1f6\uf1f7\uf1f8\uf1f9\uf1fa\uf1fb\uf1fc\uf1fd\uf1fe\uf1ff\uf200\uf201\uf202\uf203\uf204\uf205\uf206\uf207\uf208\uf209\uf20a\uf20b\uf20c\uf20d\uf20e\uf20f\uf210\uf211\uf212\uf213\uf214\uf215\uf216\uf217\uf218\uf219\uf21a\uf21b\uf21c\uf21d\uf21e\uf21f\uf220\uf221\uf222\uf223\uf224\uf225\uf226\uf227\uf228\uf229\uf22a\uf22b\uf22c\uf22d\uf22e\uf22f\uf230\uf231\uf232\uf233\uf234\uf235\uf236\uf237\uf238\uf239\uf23a\uf23b\uf23c\uf23d\uf23e\uf23f\uf240\uf241\uf242\uf243\uf244\uf245\uf246\uf247\uf248\uf249\uf24a\uf24b\uf24c\uf24d\uf24e\uf24f\uf250\uf251\uf252\uf253\uf254\uf255\uf256\uf257\uf258\uf259\uf25a\uf25b\uf25c\uf25d\uf25e\uf25f\uf260\uf261\uf262\uf263\uf264\uf265\uf266\uf267\uf268\uf269\uf26a\uf26b\uf26c\uf26d\uf26e\uf26f\uf270\uf271\uf272\uf273\uf274\uf275\uf276\uf277\uf278\uf279\uf27a\uf27b\uf27c\uf27d\uf27e\uf27f\uf280\uf281\uf282\uf283\uf284\uf285\uf286\uf287\uf288\uf289\uf28a\uf28b\uf28c\uf28d\uf28e\uf28f\uf290\uf291\uf292\uf293\uf294\uf295\uf296\uf297\uf298\uf299\uf29a\uf29b\uf29c\uf29d\uf29e\uf29f\uf2a0\uf2a1\uf2a2\uf2a3\uf2a4\uf2a5\uf2a6\uf2a7\uf2a8\uf2a9\uf2aa\uf2ab\uf2ac\uf2ad\uf2ae\uf2af\uf2b0\uf2b1\uf2b2\uf2b3\uf2b4\uf2b5\uf2b6\uf2b7\uf2b8\uf2b9\uf2ba\uf2bb\uf2bc\uf2bd\uf2be\uf2bf\uf2c0\uf2c1\uf2c2\uf2c3\uf2c4\uf2c5\uf2c6\uf2c7\uf2c8\uf2c9\uf2ca\uf2cb\uf2cc\uf2cd\uf2ce\uf2cf\uf2d0\uf2d1\uf2d2\uf2d3\uf2d4\uf2d5\uf2d6\uf2d7\uf2d8\uf2d9\uf2da\uf2db\uf2dc\uf2dd\uf2de\uf2df\uf2e0\uf2e1\uf2e2\uf2e3\uf2e4\uf2e5\uf2e6\uf2e7\uf2e8\uf2e9\uf2ea\uf2eb\uf2ec\uf2ed\uf2ee\uf2ef\uf2f0\uf2f1\uf2f2\uf2f3\uf2f4\uf2f5\uf2f6\uf2f7\uf2f8\uf2f9\uf2fa\uf2fb\uf2fc\uf2fd\uf2fe\uf2ff\uf300\uf301\uf302\uf303\uf304\uf305\uf306\uf307\uf308\uf309\uf30a\uf30b\uf30c\uf30d\uf30e\uf30f\uf310\uf311\uf312\uf313\uf314\uf315\uf316\uf317\uf318\uf319\uf31a\uf31b\uf31c\uf31d\uf31e\uf31f\uf320\uf321\uf322\uf323\uf324\uf325\uf326\uf327\uf328\uf329\uf32a\uf32b\uf32c\uf32d\uf32e\uf32f\uf330\uf331\uf332\uf333\uf334\uf335\uf336\uf337\uf338\uf339\uf33a\uf33b\uf33c\uf33d\uf33e\uf33f\uf340\uf341\uf342\uf343\uf344\uf345\uf346\uf347\uf348\uf349\uf34a\uf34b\uf34c\uf34d\uf34e\uf34f\uf350\uf351\uf352\uf353\uf354\uf355\uf356\uf357\uf358\uf359\uf35a\uf35b\uf35c\uf35d\uf35e\uf35f\uf360\uf361\uf362\uf363\uf364\uf365\uf366\uf367\uf368\uf369\uf36a\uf36b\uf36c\uf36d\uf36e\uf36f\uf370\uf371\uf372\uf373\uf374\uf375\uf376\uf377\uf378\uf379\uf37a\uf37b\uf37c\uf37d\uf37e\uf37f\uf380\uf381\uf382\uf383\uf384\uf385\uf386\uf387\uf388\uf389\uf38a\uf38b\uf38c\uf38d\uf38e\uf38f\uf390\uf391\uf392\uf393\uf394\uf395\uf396\uf397\uf398\uf399\uf39a\uf39b\uf39c\uf39d\uf39e\uf39f\uf3a0\uf3a1\uf3a2\uf3a3\uf3a4\uf3a5\uf3a6\uf3a7\uf3a8\uf3a9\uf3aa\uf3ab\uf3ac\uf3ad\uf3ae\uf3af\uf3b0\uf3b1\uf3b2\uf3b3\uf3b4\uf3b5\uf3b6\uf3b7\uf3b8\uf3b9\uf3ba\uf3bb\uf3bc\uf3bd\uf3be\uf3bf\uf3c0\uf3c1\uf3c2\uf3c3\uf3c4\uf3c5\uf3c6\uf3c7\uf3c8\uf3c9\uf3ca\uf3cb\uf3cc\uf3cd\uf3ce\uf3cf\uf3d0\uf3d1\uf3d2\uf3d3\uf3d4\uf3d5\uf3d6\uf3d7\uf3d8\uf3d9\uf3da\uf3db\uf3dc\uf3dd\uf3de\uf3df\uf3e0\uf3e1\uf3e2\uf3e3\uf3e4\uf3e5\uf3e6\uf3e7\uf3e8\uf3e9\uf3ea\uf3eb\uf3ec\uf3ed\uf3ee\uf3ef\uf3f0\uf3f1\uf3f2\uf3f3\uf3f4\uf3f5\uf3f6\uf3f7\uf3f8\uf3f9\uf3fa\uf3fb\uf3fc\uf3fd\uf3fe\uf3ff\uf400\uf401\uf402\uf403\uf404\uf405\uf406\uf407\uf408\uf409\uf40a\uf40b\uf40c\uf40d\uf40e\uf40f\uf410\uf411\uf412\uf413\uf414\uf415\uf416\uf417\uf418\uf419\uf41a\uf41b\uf41c\uf41d\uf41e\uf41f\uf420\uf421\uf422\uf423\uf424\uf425\uf426\uf427\uf428\uf429\uf42a\uf42b\uf42c\uf42d\uf42e\uf42f\uf430\uf431\uf432\uf433\uf434\uf435\uf436\uf437\uf438\uf439\uf43a\uf43b\uf43c\uf43d\uf43e\uf43f\uf440\uf441\uf442\uf443\uf444\uf445\uf446\uf447\uf448\uf449\uf44a\uf44b\uf44c\uf44d\uf44e\uf44f\uf450\uf451\uf452\uf453\uf454\uf455\uf456\uf457\uf458\uf459\uf45a\uf45b\uf45c\uf45d\uf45e\uf45f\uf460\uf461\uf462\uf463\uf464\uf465\uf466\uf467\uf468\uf469\uf46a\uf46b\uf46c\uf46d\uf46e\uf46f\uf470\uf471\uf472\uf473\uf474\uf475\uf476\uf477\uf478\uf479\uf47a\uf47b\uf47c\uf47d\uf47e\uf47f\uf480\uf481\uf482\uf483\uf484\uf485\uf486\uf487\uf488\uf489\uf48a\uf48b\uf48c\uf48d\uf48e\uf48f\uf490\uf491\uf492\uf493\uf494\uf495\uf496\uf497\uf498\uf499\uf49a\uf49b\uf49c\uf49d\uf49e\uf49f\uf4a0\uf4a1\uf4a2\uf4a3\uf4a4\uf4a5\uf4a6\uf4a7\uf4a8\uf4a9\uf4aa\uf4ab\uf4ac\uf4ad\uf4ae\uf4af\uf4b0\uf4b1\uf4b2\uf4b3\uf4b4\uf4b5\uf4b6\uf4b7\uf4b8\uf4b9\uf4ba\uf4bb\uf4bc\uf4bd\uf4be\uf4bf\uf4c0\uf4c1\uf4c2\uf4c3\uf4c4\uf4c5\uf4c6\uf4c7\uf4c8\uf4c9\uf4ca\uf4cb\uf4cc\uf4cd\uf4ce\uf4cf\uf4d0\uf4d1\uf4d2\uf4d3\uf4d4\uf4d5\uf4d6\uf4d7\uf4d8\uf4d9\uf4da\uf4db\uf4dc\uf4dd\uf4de\uf4df\uf4e0\uf4e1\uf4e2\uf4e3\uf4e4\uf4e5\uf4e6\uf4e7\uf4e8\uf4e9\uf4ea\uf4eb\uf4ec\uf4ed\uf4ee\uf4ef\uf4f0\uf4f1\uf4f2\uf4f3\uf4f4\uf4f5\uf4f6\uf4f7\uf4f8\uf4f9\uf4fa\uf4fb\uf4fc\uf4fd\uf4fe\uf4ff\uf500\uf501\uf502\uf503\uf504\uf505\uf506\uf507\uf508\uf509\uf50a\uf50b\uf50c\uf50d\uf50e\uf50f\uf510\uf511\uf512\uf513\uf514\uf515\uf516\uf517\uf518\uf519\uf51a\uf51b\uf51c\uf51d\uf51e\uf51f\uf520\uf521\uf522\uf523\uf524\uf525\uf526\uf527\uf528\uf529\uf52a\uf52b\uf52c\uf52d\uf52e\uf52f\uf530\uf531\uf532\uf533\uf534\uf535\uf536\uf537\uf538\uf539\uf53a\uf53b\uf53c\uf53d\uf53e\uf53f\uf540\uf541\uf542\uf543\uf544\uf545\uf546\uf547\uf548\uf549\uf54a\uf54b\uf54c\uf54d\uf54e\uf54f\uf550\uf551\uf552\uf553\uf554\uf555\uf556\uf557\uf558\uf559\uf55a\uf55b\uf55c\uf55d\uf55e\uf55f\uf560\uf561\uf562\uf563\uf564\uf565\uf566\uf567\uf568\uf569\uf56a\uf56b\uf56c\uf56d\uf56e\uf56f\uf570\uf571\uf572\uf573\uf574\uf575\uf576\uf577\uf578\uf579\uf57a\uf57b\uf57c\uf57d\uf57e\uf57f\uf580\uf581\uf582\uf583\uf584\uf585\uf586\uf587\uf588\uf589\uf58a\uf58b\uf58c\uf58d\uf58e\uf58f\uf590\uf591\uf592\uf593\uf594\uf595\uf596\uf597\uf598\uf599\uf59a\uf59b\uf59c\uf59d\uf59e\uf59f\uf5a0\uf5a1\uf5a2\uf5a3\uf5a4\uf5a5\uf5a6\uf5a7\uf5a8\uf5a9\uf5aa\uf5ab\uf5ac\uf5ad\uf5ae\uf5af\uf5b0\uf5b1\uf5b2\uf5b3\uf5b4\uf5b5\uf5b6\uf5b7\uf5b8\uf5b9\uf5ba\uf5bb\uf5bc\uf5bd\uf5be\uf5bf\uf5c0\uf5c1\uf5c2\uf5c3\uf5c4\uf5c5\uf5c6\uf5c7\uf5c8\uf5c9\uf5ca\uf5cb\uf5cc\uf5cd\uf5ce\uf5cf\uf5d0\uf5d1\uf5d2\uf5d3\uf5d4\uf5d5\uf5d6\uf5d7\uf5d8\uf5d9\uf5da\uf5db\uf5dc\uf5dd\uf5de\uf5df\uf5e0\uf5e1\uf5e2\uf5e3\uf5e4\uf5e5\uf5e6\uf5e7\uf5e8\uf5e9\uf5ea\uf5eb\uf5ec\uf5ed\uf5ee\uf5ef\uf5f0\uf5f1\uf5f2\uf5f3\uf5f4\uf5f5\uf5f6\uf5f7\uf5f8\uf5f9\uf5fa\uf5fb\uf5fc\uf5fd\uf5fe\uf5ff\uf600\uf601\uf602\uf603\uf604\uf605\uf606\uf607\uf608\uf609\uf60a\uf60b\uf60c\uf60d\uf60e\uf60f\uf610\uf611\uf612\uf613\uf614\uf615\uf616\uf617\uf618\uf619\uf61a\uf61b\uf61c\uf61d\uf61e\uf61f\uf620\uf621\uf622\uf623\uf624\uf625\uf626\uf627\uf628\uf629\uf62a\uf62b\uf62c\uf62d\uf62e\uf62f\uf630\uf631\uf632\uf633\uf634\uf635\uf636\uf637\uf638\uf639\uf63a\uf63b\uf63c\uf63d\uf63e\uf63f\uf640\uf641\uf642\uf643\uf644\uf645\uf646\uf647\uf648\uf649\uf64a\uf64b\uf64c\uf64d\uf64e\uf64f\uf650\uf651\uf652\uf653\uf654\uf655\uf656\uf657\uf658\uf659\uf65a\uf65b\uf65c\uf65d\uf65e\uf65f\uf660\uf661\uf662\uf663\uf664\uf665\uf666\uf667\uf668\uf669\uf66a\uf66b\uf66c\uf66d\uf66e\uf66f\uf670\uf671\uf672\uf673\uf674\uf675\uf676\uf677\uf678\uf679\uf67a\uf67b\uf67c\uf67d\uf67e\uf67f\uf680\uf681\uf682\uf683\uf684\uf685\uf686\uf687\uf688\uf689\uf68a\uf68b\uf68c\uf68d\uf68e\uf68f\uf690\uf691\uf692\uf693\uf694\uf695\uf696\uf697\uf698\uf699\uf69a\uf69b\uf69c\uf69d\uf69e\uf69f\uf6a0\uf6a1\uf6a2\uf6a3\uf6a4\uf6a5\uf6a6\uf6a7\uf6a8\uf6a9\uf6aa\uf6ab\uf6ac\uf6ad\uf6ae\uf6af\uf6b0\uf6b1\uf6b2\uf6b3\uf6b4\uf6b5\uf6b6\uf6b7\uf6b8\uf6b9\uf6ba\uf6bb\uf6bc\uf6bd\uf6be\uf6bf\uf6c0\uf6c1\uf6c2\uf6c3\uf6c4\uf6c5\uf6c6\uf6c7\uf6c8\uf6c9\uf6ca\uf6cb\uf6cc\uf6cd\uf6ce\uf6cf\uf6d0\uf6d1\uf6d2\uf6d3\uf6d4\uf6d5\uf6d6\uf6d7\uf6d8\uf6d9\uf6da\uf6db\uf6dc\uf6dd\uf6de\uf6df\uf6e0\uf6e1\uf6e2\uf6e3\uf6e4\uf6e5\uf6e6\uf6e7\uf6e8\uf6e9\uf6ea\uf6eb\uf6ec\uf6ed\uf6ee\uf6ef\uf6f0\uf6f1\uf6f2\uf6f3\uf6f4\uf6f5\uf6f6\uf6f7\uf6f8\uf6f9\uf6fa\uf6fb\uf6fc\uf6fd\uf6fe\uf6ff\uf700\uf701\uf702\uf703\uf704\uf705\uf706\uf707\uf708\uf709\uf70a\uf70b\uf70c\uf70d\uf70e\uf70f\uf710\uf711\uf712\uf713\uf714\uf715\uf716\uf717\uf718\uf719\uf71a\uf71b\uf71c\uf71d\uf71e\uf71f\uf720\uf721\uf722\uf723\uf724\uf725\uf726\uf727\uf728\uf729\uf72a\uf72b\uf72c\uf72d\uf72e\uf72f\uf730\uf731\uf732\uf733\uf734\uf735\uf736\uf737\uf738\uf739\uf73a\uf73b\uf73c\uf73d\uf73e\uf73f\uf740\uf741\uf742\uf743\uf744\uf745\uf746\uf747\uf748\uf749\uf74a\uf74b\uf74c\uf74d\uf74e\uf74f\uf750\uf751\uf752\uf753\uf754\uf755\uf756\uf757\uf758\uf759\uf75a\uf75b\uf75c\uf75d\uf75e\uf75f\uf760\uf761\uf762\uf763\uf764\uf765\uf766\uf767\uf768\uf769\uf76a\uf76b\uf76c\uf76d\uf76e\uf76f\uf770\uf771\uf772\uf773\uf774\uf775\uf776\uf777\uf778\uf779\uf77a\uf77b\uf77c\uf77d\uf77e\uf77f\uf780\uf781\uf782\uf783\uf784\uf785\uf786\uf787\uf788\uf789\uf78a\uf78b\uf78c\uf78d\uf78e\uf78f\uf790\uf791\uf792\uf793\uf794\uf795\uf796\uf797\uf798\uf799\uf79a\uf79b\uf79c\uf79d\uf79e\uf79f\uf7a0\uf7a1\uf7a2\uf7a3\uf7a4\uf7a5\uf7a6\uf7a7\uf7a8\uf7a9\uf7aa\uf7ab\uf7ac\uf7ad\uf7ae\uf7af\uf7b0\uf7b1\uf7b2\uf7b3\uf7b4\uf7b5\uf7b6\uf7b7\uf7b8\uf7b9\uf7ba\uf7bb\uf7bc\uf7bd\uf7be\uf7bf\uf7c0\uf7c1\uf7c2\uf7c3\uf7c4\uf7c5\uf7c6\uf7c7\uf7c8\uf7c9\uf7ca\uf7cb\uf7cc\uf7cd\uf7ce\uf7cf\uf7d0\uf7d1\uf7d2\uf7d3\uf7d4\uf7d5\uf7d6\uf7d7\uf7d8\uf7d9\uf7da\uf7db\uf7dc\uf7dd\uf7de\uf7df\uf7e0\uf7e1\uf7e2\uf7e3\uf7e4\uf7e5\uf7e6\uf7e7\uf7e8\uf7e9\uf7ea\uf7eb\uf7ec\uf7ed\uf7ee\uf7ef\uf7f0\uf7f1\uf7f2\uf7f3\uf7f4\uf7f5\uf7f6\uf7f7\uf7f8\uf7f9\uf7fa\uf7fb\uf7fc\uf7fd\uf7fe\uf7ff\uf800\uf801\uf802\uf803\uf804\uf805\uf806\uf807\uf808\uf809\uf80a\uf80b\uf80c\uf80d\uf80e\uf80f\uf810\uf811\uf812\uf813\uf814\uf815\uf816\uf817\uf818\uf819\uf81a\uf81b\uf81c\uf81d\uf81e\uf81f\uf820\uf821\uf822\uf823\uf824\uf825\uf826\uf827\uf828\uf829\uf82a\uf82b\uf82c\uf82d\uf82e\uf82f\uf830\uf831\uf832\uf833\uf834\uf835\uf836\uf837\uf838\uf839\uf83a\uf83b\uf83c\uf83d\uf83e\uf83f\uf840\uf841\uf842\uf843\uf844\uf845\uf846\uf847\uf848\uf849\uf84a\uf84b\uf84c\uf84d\uf84e\uf84f\uf850\uf851\uf852\uf853\uf854\uf855\uf856\uf857\uf858\uf859\uf85a\uf85b\uf85c\uf85d\uf85e\uf85f\uf860\uf861\uf862\uf863\uf864\uf865\uf866\uf867\uf868\uf869\uf86a\uf86b\uf86c\uf86d\uf86e\uf86f\uf870\uf871\uf872\uf873\uf874\uf875\uf876\uf877\uf878\uf879\uf87a\uf87b\uf87c\uf87d\uf87e\uf87f\uf880\uf881\uf882\uf883\uf884\uf885\uf886\uf887\uf888\uf889\uf88a\uf88b\uf88c\uf88d\uf88e\uf88f\uf890\uf891\uf892\uf893\uf894\uf895\uf896\uf897\uf898\uf899\uf89a\uf89b\uf89c\uf89d\uf89e\uf89f\uf8a0\uf8a1\uf8a2\uf8a3\uf8a4\uf8a5\uf8a6\uf8a7\uf8a8\uf8a9\uf8aa\uf8ab\uf8ac\uf8ad\uf8ae\uf8af\uf8b0\uf8b1\uf8b2\uf8b3\uf8b4\uf8b5\uf8b6\uf8b7\uf8b8\uf8b9\uf8ba\uf8bb\uf8bc\uf8bd\uf8be\uf8bf\uf8c0\uf8c1\uf8c2\uf8c3\uf8c4\uf8c5\uf8c6\uf8c7\uf8c8\uf8c9\uf8ca\uf8cb\uf8cc\uf8cd\uf8ce\uf8cf\uf8d0\uf8d1\uf8d2\uf8d3\uf8d4\uf8d5\uf8d6\uf8d7\uf8d8\uf8d9\uf8da\uf8db\uf8dc\uf8dd\uf8de\uf8df\uf8e0\uf8e1\uf8e2\uf8e3\uf8e4\uf8e5\uf8e6\uf8e7\uf8e8\uf8e9\uf8ea\uf8eb\uf8ec\uf8ed\uf8ee\uf8ef\uf8f0\uf8f1\uf8f2\uf8f3\uf8f4\uf8f5\uf8f6\uf8f7\uf8f8\uf8f9\uf8fa\uf8fb\uf8fc\uf8fd\uf8fe\uf8ff'
+
+try:
+ Cs = eval(r"'\ud800\ud801\ud802\ud803\ud804\ud805\ud806\ud807\ud808\ud809\ud80a\ud80b\ud80c\ud80d\ud80e\ud80f\ud810\ud811\ud812\ud813\ud814\ud815\ud816\ud817\ud818\ud819\ud81a\ud81b\ud81c\ud81d\ud81e\ud81f\ud820\ud821\ud822\ud823\ud824\ud825\ud826\ud827\ud828\ud829\ud82a\ud82b\ud82c\ud82d\ud82e\ud82f\ud830\ud831\ud832\ud833\ud834\ud835\ud836\ud837\ud838\ud839\ud83a\ud83b\ud83c\ud83d\ud83e\ud83f\ud840\ud841\ud842\ud843\ud844\ud845\ud846\ud847\ud848\ud849\ud84a\ud84b\ud84c\ud84d\ud84e\ud84f\ud850\ud851\ud852\ud853\ud854\ud855\ud856\ud857\ud858\ud859\ud85a\ud85b\ud85c\ud85d\ud85e\ud85f\ud860\ud861\ud862\ud863\ud864\ud865\ud866\ud867\ud868\ud869\ud86a\ud86b\ud86c\ud86d\ud86e\ud86f\ud870\ud871\ud872\ud873\ud874\ud875\ud876\ud877\ud878\ud879\ud87a\ud87b\ud87c\ud87d\ud87e\ud87f\ud880\ud881\ud882\ud883\ud884\ud885\ud886\ud887\ud888\ud889\ud88a\ud88b\ud88c\ud88d\ud88e\ud88f\ud890\ud891\ud892\ud893\ud894\ud895\ud896\ud897\ud898\ud899\ud89a\ud89b\ud89c\ud89d\ud89e\ud89f\ud8a0\ud8a1\ud8a2\ud8a3\ud8a4\ud8a5\ud8a6\ud8a7\ud8a8\ud8a9\ud8aa\ud8ab\ud8ac\ud8ad\ud8ae\ud8af\ud8b0\ud8b1\ud8b2\ud8b3\ud8b4\ud8b5\ud8b6\ud8b7\ud8b8\ud8b9\ud8ba\ud8bb\ud8bc\ud8bd\ud8be\ud8bf\ud8c0\ud8c1\ud8c2\ud8c3\ud8c4\ud8c5\ud8c6\ud8c7\ud8c8\ud8c9\ud8ca\ud8cb\ud8cc\ud8cd\ud8ce\ud8cf\ud8d0\ud8d1\ud8d2\ud8d3\ud8d4\ud8d5\ud8d6\ud8d7\ud8d8\ud8d9\ud8da\ud8db\ud8dc\ud8dd\ud8de\ud8df\ud8e0\ud8e1\ud8e2\ud8e3\ud8e4\ud8e5\ud8e6\ud8e7\ud8e8\ud8e9\ud8ea\ud8eb\ud8ec\ud8ed\ud8ee\ud8ef\ud8f0\ud8f1\ud8f2\ud8f3\ud8f4\ud8f5\ud8f6\ud8f7\ud8f8\ud8f9\ud8fa\ud8fb\ud8fc\ud8fd\ud8fe\ud8ff\ud900\ud901\ud902\ud903\ud904\ud905\ud906\ud907\ud908\ud909\ud90a\ud90b\ud90c\ud90d\ud90e\ud90f\ud910\ud911\ud912\ud913\ud914\ud915\ud916\ud917\ud918\ud919\ud91a\ud91b\ud91c\ud91d\ud91e\ud91f\ud920\ud921\ud922\ud923\ud924\ud925\ud926\ud927\ud928\ud929\ud92a\ud92b\ud92c\ud92d\ud92e\ud92f\ud930\ud931\ud932\ud933\ud934\ud935\ud936\ud937\ud938\ud939\ud93a\ud93b\ud93c\ud93d\ud93e\ud93f\ud940\ud941\ud942\ud943\ud944\ud945\ud946\ud947\ud948\ud949\ud94a\ud94b\ud94c\ud94d\ud94e\ud94f\ud950\ud951\ud952\ud953\ud954\ud955\ud956\ud957\ud958\ud959\ud95a\ud95b\ud95c\ud95d\ud95e\ud95f\ud960\ud961\ud962\ud963\ud964\ud965\ud966\ud967\ud968\ud969\ud96a\ud96b\ud96c\ud96d\ud96e\ud96f\ud970\ud971\ud972\ud973\ud974\ud975\ud976\ud977\ud978\ud979\ud97a\ud97b\ud97c\ud97d\ud97e\ud97f\ud980\ud981\ud982\ud983\ud984\ud985\ud986\ud987\ud988\ud989\ud98a\ud98b\ud98c\ud98d\ud98e\ud98f\ud990\ud991\ud992\ud993\ud994\ud995\ud996\ud997\ud998\ud999\ud99a\ud99b\ud99c\ud99d\ud99e\ud99f\ud9a0\ud9a1\ud9a2\ud9a3\ud9a4\ud9a5\ud9a6\ud9a7\ud9a8\ud9a9\ud9aa\ud9ab\ud9ac\ud9ad\ud9ae\ud9af\ud9b0\ud9b1\ud9b2\ud9b3\ud9b4\ud9b5\ud9b6\ud9b7\ud9b8\ud9b9\ud9ba\ud9bb\ud9bc\ud9bd\ud9be\ud9bf\ud9c0\ud9c1\ud9c2\ud9c3\ud9c4\ud9c5\ud9c6\ud9c7\ud9c8\ud9c9\ud9ca\ud9cb\ud9cc\ud9cd\ud9ce\ud9cf\ud9d0\ud9d1\ud9d2\ud9d3\ud9d4\ud9d5\ud9d6\ud9d7\ud9d8\ud9d9\ud9da\ud9db\ud9dc\ud9dd\ud9de\ud9df\ud9e0\ud9e1\ud9e2\ud9e3\ud9e4\ud9e5\ud9e6\ud9e7\ud9e8\ud9e9\ud9ea\ud9eb\ud9ec\ud9ed\ud9ee\ud9ef\ud9f0\ud9f1\ud9f2\ud9f3\ud9f4\ud9f5\ud9f6\ud9f7\ud9f8\ud9f9\ud9fa\ud9fb\ud9fc\ud9fd\ud9fe\ud9ff\uda00\uda01\uda02\uda03\uda04\uda05\uda06\uda07\uda08\uda09\uda0a\uda0b\uda0c\uda0d\uda0e\uda0f\uda10\uda11\uda12\uda13\uda14\uda15\uda16\uda17\uda18\uda19\uda1a\uda1b\uda1c\uda1d\uda1e\uda1f\uda20\uda21\uda22\uda23\uda24\uda25\uda26\uda27\uda28\uda29\uda2a\uda2b\uda2c\uda2d\uda2e\uda2f\uda30\uda31\uda32\uda33\uda34\uda35\uda36\uda37\uda38\uda39\uda3a\uda3b\uda3c\uda3d\uda3e\uda3f\uda40\uda41\uda42\uda43\uda44\uda45\uda46\uda47\uda48\uda49\uda4a\uda4b\uda4c\uda4d\uda4e\uda4f\uda50\uda51\uda52\uda53\uda54\uda55\uda56\uda57\uda58\uda59\uda5a\uda5b\uda5c\uda5d\uda5e\uda5f\uda60\uda61\uda62\uda63\uda64\uda65\uda66\uda67\uda68\uda69\uda6a\uda6b\uda6c\uda6d\uda6e\uda6f\uda70\uda71\uda72\uda73\uda74\uda75\uda76\uda77\uda78\uda79\uda7a\uda7b\uda7c\uda7d\uda7e\uda7f\uda80\uda81\uda82\uda83\uda84\uda85\uda86\uda87\uda88\uda89\uda8a\uda8b\uda8c\uda8d\uda8e\uda8f\uda90\uda91\uda92\uda93\uda94\uda95\uda96\uda97\uda98\uda99\uda9a\uda9b\uda9c\uda9d\uda9e\uda9f\udaa0\udaa1\udaa2\udaa3\udaa4\udaa5\udaa6\udaa7\udaa8\udaa9\udaaa\udaab\udaac\udaad\udaae\udaaf\udab0\udab1\udab2\udab3\udab4\udab5\udab6\udab7\udab8\udab9\udaba\udabb\udabc\udabd\udabe\udabf\udac0\udac1\udac2\udac3\udac4\udac5\udac6\udac7\udac8\udac9\udaca\udacb\udacc\udacd\udace\udacf\udad0\udad1\udad2\udad3\udad4\udad5\udad6\udad7\udad8\udad9\udada\udadb\udadc\udadd\udade\udadf\udae0\udae1\udae2\udae3\udae4\udae5\udae6\udae7\udae8\udae9\udaea\udaeb\udaec\udaed\udaee\udaef\udaf0\udaf1\udaf2\udaf3\udaf4\udaf5\udaf6\udaf7\udaf8\udaf9\udafa\udafb\udafc\udafd\udafe\udaff\udb00\udb01\udb02\udb03\udb04\udb05\udb06\udb07\udb08\udb09\udb0a\udb0b\udb0c\udb0d\udb0e\udb0f\udb10\udb11\udb12\udb13\udb14\udb15\udb16\udb17\udb18\udb19\udb1a\udb1b\udb1c\udb1d\udb1e\udb1f\udb20\udb21\udb22\udb23\udb24\udb25\udb26\udb27\udb28\udb29\udb2a\udb2b\udb2c\udb2d\udb2e\udb2f\udb30\udb31\udb32\udb33\udb34\udb35\udb36\udb37\udb38\udb39\udb3a\udb3b\udb3c\udb3d\udb3e\udb3f\udb40\udb41\udb42\udb43\udb44\udb45\udb46\udb47\udb48\udb49\udb4a\udb4b\udb4c\udb4d\udb4e\udb4f\udb50\udb51\udb52\udb53\udb54\udb55\udb56\udb57\udb58\udb59\udb5a\udb5b\udb5c\udb5d\udb5e\udb5f\udb60\udb61\udb62\udb63\udb64\udb65\udb66\udb67\udb68\udb69\udb6a\udb6b\udb6c\udb6d\udb6e\udb6f\udb70\udb71\udb72\udb73\udb74\udb75\udb76\udb77\udb78\udb79\udb7a\udb7b\udb7c\udb7d\udb7e\udb7f\udb80\udb81\udb82\udb83\udb84\udb85\udb86\udb87\udb88\udb89\udb8a\udb8b\udb8c\udb8d\udb8e\udb8f\udb90\udb91\udb92\udb93\udb94\udb95\udb96\udb97\udb98\udb99\udb9a\udb9b\udb9c\udb9d\udb9e\udb9f\udba0\udba1\udba2\udba3\udba4\udba5\udba6\udba7\udba8\udba9\udbaa\udbab\udbac\udbad\udbae\udbaf\udbb0\udbb1\udbb2\udbb3\udbb4\udbb5\udbb6\udbb7\udbb8\udbb9\udbba\udbbb\udbbc\udbbd\udbbe\udbbf\udbc0\udbc1\udbc2\udbc3\udbc4\udbc5\udbc6\udbc7\udbc8\udbc9\udbca\udbcb\udbcc\udbcd\udbce\udbcf\udbd0\udbd1\udbd2\udbd3\udbd4\udbd5\udbd6\udbd7\udbd8\udbd9\udbda\udbdb\udbdc\udbdd\udbde\udbdf\udbe0\udbe1\udbe2\udbe3\udbe4\udbe5\udbe6\udbe7\udbe8\udbe9\udbea\udbeb\udbec\udbed\udbee\udbef\udbf0\udbf1\udbf2\udbf3\udbf4\udbf5\udbf6\udbf7\udbf8\udbf9\udbfa\udbfb\udbfc\udbfd\udbfe\U0010fc00\udc01\udc02\udc03\udc04\udc05\udc06\udc07\udc08\udc09\udc0a\udc0b\udc0c\udc0d\udc0e\udc0f\udc10\udc11\udc12\udc13\udc14\udc15\udc16\udc17\udc18\udc19\udc1a\udc1b\udc1c\udc1d\udc1e\udc1f\udc20\udc21\udc22\udc23\udc24\udc25\udc26\udc27\udc28\udc29\udc2a\udc2b\udc2c\udc2d\udc2e\udc2f\udc30\udc31\udc32\udc33\udc34\udc35\udc36\udc37\udc38\udc39\udc3a\udc3b\udc3c\udc3d\udc3e\udc3f\udc40\udc41\udc42\udc43\udc44\udc45\udc46\udc47\udc48\udc49\udc4a\udc4b\udc4c\udc4d\udc4e\udc4f\udc50\udc51\udc52\udc53\udc54\udc55\udc56\udc57\udc58\udc59\udc5a\udc5b\udc5c\udc5d\udc5e\udc5f\udc60\udc61\udc62\udc63\udc64\udc65\udc66\udc67\udc68\udc69\udc6a\udc6b\udc6c\udc6d\udc6e\udc6f\udc70\udc71\udc72\udc73\udc74\udc75\udc76\udc77\udc78\udc79\udc7a\udc7b\udc7c\udc7d\udc7e\udc7f\udc80\udc81\udc82\udc83\udc84\udc85\udc86\udc87\udc88\udc89\udc8a\udc8b\udc8c\udc8d\udc8e\udc8f\udc90\udc91\udc92\udc93\udc94\udc95\udc96\udc97\udc98\udc99\udc9a\udc9b\udc9c\udc9d\udc9e\udc9f\udca0\udca1\udca2\udca3\udca4\udca5\udca6\udca7\udca8\udca9\udcaa\udcab\udcac\udcad\udcae\udcaf\udcb0\udcb1\udcb2\udcb3\udcb4\udcb5\udcb6\udcb7\udcb8\udcb9\udcba\udcbb\udcbc\udcbd\udcbe\udcbf\udcc0\udcc1\udcc2\udcc3\udcc4\udcc5\udcc6\udcc7\udcc8\udcc9\udcca\udccb\udccc\udccd\udcce\udccf\udcd0\udcd1\udcd2\udcd3\udcd4\udcd5\udcd6\udcd7\udcd8\udcd9\udcda\udcdb\udcdc\udcdd\udcde\udcdf\udce0\udce1\udce2\udce3\udce4\udce5\udce6\udce7\udce8\udce9\udcea\udceb\udcec\udced\udcee\udcef\udcf0\udcf1\udcf2\udcf3\udcf4\udcf5\udcf6\udcf7\udcf8\udcf9\udcfa\udcfb\udcfc\udcfd\udcfe\udcff\udd00\udd01\udd02\udd03\udd04\udd05\udd06\udd07\udd08\udd09\udd0a\udd0b\udd0c\udd0d\udd0e\udd0f\udd10\udd11\udd12\udd13\udd14\udd15\udd16\udd17\udd18\udd19\udd1a\udd1b\udd1c\udd1d\udd1e\udd1f\udd20\udd21\udd22\udd23\udd24\udd25\udd26\udd27\udd28\udd29\udd2a\udd2b\udd2c\udd2d\udd2e\udd2f\udd30\udd31\udd32\udd33\udd34\udd35\udd36\udd37\udd38\udd39\udd3a\udd3b\udd3c\udd3d\udd3e\udd3f\udd40\udd41\udd42\udd43\udd44\udd45\udd46\udd47\udd48\udd49\udd4a\udd4b\udd4c\udd4d\udd4e\udd4f\udd50\udd51\udd52\udd53\udd54\udd55\udd56\udd57\udd58\udd59\udd5a\udd5b\udd5c\udd5d\udd5e\udd5f\udd60\udd61\udd62\udd63\udd64\udd65\udd66\udd67\udd68\udd69\udd6a\udd6b\udd6c\udd6d\udd6e\udd6f\udd70\udd71\udd72\udd73\udd74\udd75\udd76\udd77\udd78\udd79\udd7a\udd7b\udd7c\udd7d\udd7e\udd7f\udd80\udd81\udd82\udd83\udd84\udd85\udd86\udd87\udd88\udd89\udd8a\udd8b\udd8c\udd8d\udd8e\udd8f\udd90\udd91\udd92\udd93\udd94\udd95\udd96\udd97\udd98\udd99\udd9a\udd9b\udd9c\udd9d\udd9e\udd9f\udda0\udda1\udda2\udda3\udda4\udda5\udda6\udda7\udda8\udda9\uddaa\uddab\uddac\uddad\uddae\uddaf\uddb0\uddb1\uddb2\uddb3\uddb4\uddb5\uddb6\uddb7\uddb8\uddb9\uddba\uddbb\uddbc\uddbd\uddbe\uddbf\uddc0\uddc1\uddc2\uddc3\uddc4\uddc5\uddc6\uddc7\uddc8\uddc9\uddca\uddcb\uddcc\uddcd\uddce\uddcf\uddd0\uddd1\uddd2\uddd3\uddd4\uddd5\uddd6\uddd7\uddd8\uddd9\uddda\udddb\udddc\udddd\uddde\udddf\udde0\udde1\udde2\udde3\udde4\udde5\udde6\udde7\udde8\udde9\uddea\uddeb\uddec\udded\uddee\uddef\uddf0\uddf1\uddf2\uddf3\uddf4\uddf5\uddf6\uddf7\uddf8\uddf9\uddfa\uddfb\uddfc\uddfd\uddfe\uddff\ude00\ude01\ude02\ude03\ude04\ude05\ude06\ude07\ude08\ude09\ude0a\ude0b\ude0c\ude0d\ude0e\ude0f\ude10\ude11\ude12\ude13\ude14\ude15\ude16\ude17\ude18\ude19\ude1a\ude1b\ude1c\ude1d\ude1e\ude1f\ude20\ude21\ude22\ude23\ude24\ude25\ude26\ude27\ude28\ude29\ude2a\ude2b\ude2c\ude2d\ude2e\ude2f\ude30\ude31\ude32\ude33\ude34\ude35\ude36\ude37\ude38\ude39\ude3a\ude3b\ude3c\ude3d\ude3e\ude3f\ude40\ude41\ude42\ude43\ude44\ude45\ude46\ude47\ude48\ude49\ude4a\ude4b\ude4c\ude4d\ude4e\ude4f\ude50\ude51\ude52\ude53\ude54\ude55\ude56\ude57\ude58\ude59\ude5a\ude5b\ude5c\ude5d\ude5e\ude5f\ude60\ude61\ude62\ude63\ude64\ude65\ude66\ude67\ude68\ude69\ude6a\ude6b\ude6c\ude6d\ude6e\ude6f\ude70\ude71\ude72\ude73\ude74\ude75\ude76\ude77\ude78\ude79\ude7a\ude7b\ude7c\ude7d\ude7e\ude7f\ude80\ude81\ude82\ude83\ude84\ude85\ude86\ude87\ude88\ude89\ude8a\ude8b\ude8c\ude8d\ude8e\ude8f\ude90\ude91\ude92\ude93\ude94\ude95\ude96\ude97\ude98\ude99\ude9a\ude9b\ude9c\ude9d\ude9e\ude9f\udea0\udea1\udea2\udea3\udea4\udea5\udea6\udea7\udea8\udea9\udeaa\udeab\udeac\udead\udeae\udeaf\udeb0\udeb1\udeb2\udeb3\udeb4\udeb5\udeb6\udeb7\udeb8\udeb9\udeba\udebb\udebc\udebd\udebe\udebf\udec0\udec1\udec2\udec3\udec4\udec5\udec6\udec7\udec8\udec9\udeca\udecb\udecc\udecd\udece\udecf\uded0\uded1\uded2\uded3\uded4\uded5\uded6\uded7\uded8\uded9\udeda\udedb\udedc\udedd\udede\udedf\udee0\udee1\udee2\udee3\udee4\udee5\udee6\udee7\udee8\udee9\udeea\udeeb\udeec\udeed\udeee\udeef\udef0\udef1\udef2\udef3\udef4\udef5\udef6\udef7\udef8\udef9\udefa\udefb\udefc\udefd\udefe\udeff\udf00\udf01\udf02\udf03\udf04\udf05\udf06\udf07\udf08\udf09\udf0a\udf0b\udf0c\udf0d\udf0e\udf0f\udf10\udf11\udf12\udf13\udf14\udf15\udf16\udf17\udf18\udf19\udf1a\udf1b\udf1c\udf1d\udf1e\udf1f\udf20\udf21\udf22\udf23\udf24\udf25\udf26\udf27\udf28\udf29\udf2a\udf2b\udf2c\udf2d\udf2e\udf2f\udf30\udf31\udf32\udf33\udf34\udf35\udf36\udf37\udf38\udf39\udf3a\udf3b\udf3c\udf3d\udf3e\udf3f\udf40\udf41\udf42\udf43\udf44\udf45\udf46\udf47\udf48\udf49\udf4a\udf4b\udf4c\udf4d\udf4e\udf4f\udf50\udf51\udf52\udf53\udf54\udf55\udf56\udf57\udf58\udf59\udf5a\udf5b\udf5c\udf5d\udf5e\udf5f\udf60\udf61\udf62\udf63\udf64\udf65\udf66\udf67\udf68\udf69\udf6a\udf6b\udf6c\udf6d\udf6e\udf6f\udf70\udf71\udf72\udf73\udf74\udf75\udf76\udf77\udf78\udf79\udf7a\udf7b\udf7c\udf7d\udf7e\udf7f\udf80\udf81\udf82\udf83\udf84\udf85\udf86\udf87\udf88\udf89\udf8a\udf8b\udf8c\udf8d\udf8e\udf8f\udf90\udf91\udf92\udf93\udf94\udf95\udf96\udf97\udf98\udf99\udf9a\udf9b\udf9c\udf9d\udf9e\udf9f\udfa0\udfa1\udfa2\udfa3\udfa4\udfa5\udfa6\udfa7\udfa8\udfa9\udfaa\udfab\udfac\udfad\udfae\udfaf\udfb0\udfb1\udfb2\udfb3\udfb4\udfb5\udfb6\udfb7\udfb8\udfb9\udfba\udfbb\udfbc\udfbd\udfbe\udfbf\udfc0\udfc1\udfc2\udfc3\udfc4\udfc5\udfc6\udfc7\udfc8\udfc9\udfca\udfcb\udfcc\udfcd\udfce\udfcf\udfd0\udfd1\udfd2\udfd3\udfd4\udfd5\udfd6\udfd7\udfd8\udfd9\udfda\udfdb\udfdc\udfdd\udfde\udfdf\udfe0\udfe1\udfe2\udfe3\udfe4\udfe5\udfe6\udfe7\udfe8\udfe9\udfea\udfeb\udfec\udfed\udfee\udfef\udff0\udff1\udff2\udff3\udff4\udff5\udff6\udff7\udff8\udff9\udffa\udffb\udffc\udffd\udffe\udfff'")
+except UnicodeDecodeError:
+ Cs = '' # Jython can't handle isolated surrogates
+
+Ll = u'abcdefghijklmnopqrstuvwxyz\xaa\xb5\xba\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff\u0101\u0103\u0105\u0107\u0109\u010b\u010d\u010f\u0111\u0113\u0115\u0117\u0119\u011b\u011d\u011f\u0121\u0123\u0125\u0127\u0129\u012b\u012d\u012f\u0131\u0133\u0135\u0137\u0138\u013a\u013c\u013e\u0140\u0142\u0144\u0146\u0148\u0149\u014b\u014d\u014f\u0151\u0153\u0155\u0157\u0159\u015b\u015d\u015f\u0161\u0163\u0165\u0167\u0169\u016b\u016d\u016f\u0171\u0173\u0175\u0177\u017a\u017c\u017e\u017f\u0180\u0183\u0185\u0188\u018c\u018d\u0192\u0195\u0199\u019a\u019b\u019e\u01a1\u01a3\u01a5\u01a8\u01aa\u01ab\u01ad\u01b0\u01b4\u01b6\u01b9\u01ba\u01bd\u01be\u01bf\u01c6\u01c9\u01cc\u01ce\u01d0\u01d2\u01d4\u01d6\u01d8\u01da\u01dc\u01dd\u01df\u01e1\u01e3\u01e5\u01e7\u01e9\u01eb\u01ed\u01ef\u01f0\u01f3\u01f5\u01f9\u01fb\u01fd\u01ff\u0201\u0203\u0205\u0207\u0209\u020b\u020d\u020f\u0211\u0213\u0215\u0217\u0219\u021b\u021d\u021f\u0221\u0223\u0225\u0227\u0229\u022b\u022d\u022f\u0231\u0233\u0234\u0235\u0236\u0237\u0238\u0239\u023c\u023f\u0240\u0250\u0251\u0252\u0253\u0254\u0255\u0256\u0257\u0258\u0259\u025a\u025b\u025c\u025d\u025e\u025f\u0260\u0261\u0262\u0263\u0264\u0265\u0266\u0267\u0268\u0269\u026a\u026b\u026c\u026d\u026e\u026f\u0270\u0271\u0272\u0273\u0274\u0275\u0276\u0277\u0278\u0279\u027a\u027b\u027c\u027d\u027e\u027f\u0280\u0281\u0282\u0283\u0284\u0285\u0286\u0287\u0288\u0289\u028a\u028b\u028c\u028d\u028e\u028f\u0290\u0291\u0292\u0293\u0294\u0295\u0296\u0297\u0298\u0299\u029a\u029b\u029c\u029d\u029e\u029f\u02a0\u02a1\u02a2\u02a3\u02a4\u02a5\u02a6\u02a7\u02a8\u02a9\u02aa\u02ab\u02ac\u02ad\u02ae\u02af\u0390\u03ac\u03ad\u03ae\u03af\u03b0\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c2\u03c3\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9\u03ca\u03cb\u03cc\u03cd\u03ce\u03d0\u03d1\u03d5\u03d6\u03d7\u03d9\u03db\u03dd\u03df\u03e1\u03e3\u03e5\u03e7\u03e9\u03eb\u03ed\u03ef\u03f0\u03f1\u03f2\u03f3\u03f5\u03f8\u03fb\u03fc\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043a\u043b\u043c\u043d\u043e\u043f\u0440\u0441\u0442\u0443\u0444\u0445\u0446\u0447\u0448\u0449\u044a\u044b\u044c\u044d\u044e\u044f\u0450\u0451\u0452\u0453\u0454\u0455\u0456\u0457\u0458\u0459\u045a\u045b\u045c\u045d\u045e\u045f\u0461\u0463\u0465\u0467\u0469\u046b\u046d\u046f\u0471\u0473\u0475\u0477\u0479\u047b\u047d\u047f\u0481\u048b\u048d\u048f\u0491\u0493\u0495\u0497\u0499\u049b\u049d\u049f\u04a1\u04a3\u04a5\u04a7\u04a9\u04ab\u04ad\u04af\u04b1\u04b3\u04b5\u04b7\u04b9\u04bb\u04bd\u04bf\u04c2\u04c4\u04c6\u04c8\u04ca\u04cc\u04ce\u04d1\u04d3\u04d5\u04d7\u04d9\u04db\u04dd\u04df\u04e1\u04e3\u04e5\u04e7\u04e9\u04eb\u04ed\u04ef\u04f1\u04f3\u04f5\u04f7\u04f9\u0501\u0503\u0505\u0507\u0509\u050b\u050d\u050f\u0561\u0562\u0563\u0564\u0565\u0566\u0567\u0568\u0569\u056a\u056b\u056c\u056d\u056e\u056f\u0570\u0571\u0572\u0573\u0574\u0575\u0576\u0577\u0578\u0579\u057a\u057b\u057c\u057d\u057e\u057f\u0580\u0581\u0582\u0583\u0584\u0585\u0586\u0587\u1d00\u1d01\u1d02\u1d03\u1d04\u1d05\u1d06\u1d07\u1d08\u1d09\u1d0a\u1d0b\u1d0c\u1d0d\u1d0e\u1d0f\u1d10\u1d11\u1d12\u1d13\u1d14\u1d15\u1d16\u1d17\u1d18\u1d19\u1d1a\u1d1b\u1d1c\u1d1d\u1d1e\u1d1f\u1d20\u1d21\u1d22\u1d23\u1d24\u1d25\u1d26\u1d27\u1d28\u1d29\u1d2a\u1d2b\u1d62\u1d63\u1d64\u1d65\u1d66\u1d67\u1d68\u1d69\u1d6a\u1d6b\u1d6c\u1d6d\u1d6e\u1d6f\u1d70\u1d71\u1d72\u1d73\u1d74\u1d75\u1d76\u1d77\u1d79\u1d7a\u1d7b\u1d7c\u1d7d\u1d7e\u1d7f\u1d80\u1d81\u1d82\u1d83\u1d84\u1d85\u1d86\u1d87\u1d88\u1d89\u1d8a\u1d8b\u1d8c\u1d8d\u1d8e\u1d8f\u1d90\u1d91\u1d92\u1d93\u1d94\u1d95\u1d96\u1d97\u1d98\u1d99\u1d9a\u1e01\u1e03\u1e05\u1e07\u1e09\u1e0b\u1e0d\u1e0f\u1e11\u1e13\u1e15\u1e17\u1e19\u1e1b\u1e1d\u1e1f\u1e21\u1e23\u1e25\u1e27\u1e29\u1e2b\u1e2d\u1e2f\u1e31\u1e33\u1e35\u1e37\u1e39\u1e3b\u1e3d\u1e3f\u1e41\u1e43\u1e45\u1e47\u1e49\u1e4b\u1e4d\u1e4f\u1e51\u1e53\u1e55\u1e57\u1e59\u1e5b\u1e5d\u1e5f\u1e61\u1e63\u1e65\u1e67\u1e69\u1e6b\u1e6d\u1e6f\u1e71\u1e73\u1e75\u1e77\u1e79\u1e7b\u1e7d\u1e7f\u1e81\u1e83\u1e85\u1e87\u1e89\u1e8b\u1e8d\u1e8f\u1e91\u1e93\u1e95\u1e96\u1e97\u1e98\u1e99\u1e9a\u1e9b\u1ea1\u1ea3\u1ea5\u1ea7\u1ea9\u1eab\u1ead\u1eaf\u1eb1\u1eb3\u1eb5\u1eb7\u1eb9\u1ebb\u1ebd\u1ebf\u1ec1\u1ec3\u1ec5\u1ec7\u1ec9\u1ecb\u1ecd\u1ecf\u1ed1\u1ed3\u1ed5\u1ed7\u1ed9\u1edb\u1edd\u1edf\u1ee1\u1ee3\u1ee5\u1ee7\u1ee9\u1eeb\u1eed\u1eef\u1ef1\u1ef3\u1ef5\u1ef7\u1ef9\u1f00\u1f01\u1f02\u1f03\u1f04\u1f05\u1f06\u1f07\u1f10\u1f11\u1f12\u1f13\u1f14\u1f15\u1f20\u1f21\u1f22\u1f23\u1f24\u1f25\u1f26\u1f27\u1f30\u1f31\u1f32\u1f33\u1f34\u1f35\u1f36\u1f37\u1f40\u1f41\u1f42\u1f43\u1f44\u1f45\u1f50\u1f51\u1f52\u1f53\u1f54\u1f55\u1f56\u1f57\u1f60\u1f61\u1f62\u1f63\u1f64\u1f65\u1f66\u1f67\u1f70\u1f71\u1f72\u1f73\u1f74\u1f75\u1f76\u1f77\u1f78\u1f79\u1f7a\u1f7b\u1f7c\u1f7d\u1f80\u1f81\u1f82\u1f83\u1f84\u1f85\u1f86\u1f87\u1f90\u1f91\u1f92\u1f93\u1f94\u1f95\u1f96\u1f97\u1fa0\u1fa1\u1fa2\u1fa3\u1fa4\u1fa5\u1fa6\u1fa7\u1fb0\u1fb1\u1fb2\u1fb3\u1fb4\u1fb6\u1fb7\u1fbe\u1fc2\u1fc3\u1fc4\u1fc6\u1fc7\u1fd0\u1fd1\u1fd2\u1fd3\u1fd6\u1fd7\u1fe0\u1fe1\u1fe2\u1fe3\u1fe4\u1fe5\u1fe6\u1fe7\u1ff2\u1ff3\u1ff4\u1ff6\u1ff7\u2071\u207f\u210a\u210e\u210f\u2113\u212f\u2134\u2139\u213c\u213d\u2146\u2147\u2148\u2149\u2c30\u2c31\u2c32\u2c33\u2c34\u2c35\u2c36\u2c37\u2c38\u2c39\u2c3a\u2c3b\u2c3c\u2c3d\u2c3e\u2c3f\u2c40\u2c41\u2c42\u2c43\u2c44\u2c45\u2c46\u2c47\u2c48\u2c49\u2c4a\u2c4b\u2c4c\u2c4d\u2c4e\u2c4f\u2c50\u2c51\u2c52\u2c53\u2c54\u2c55\u2c56\u2c57\u2c58\u2c59\u2c5a\u2c5b\u2c5c\u2c5d\u2c5e\u2c81\u2c83\u2c85\u2c87\u2c89\u2c8b\u2c8d\u2c8f\u2c91\u2c93\u2c95\u2c97\u2c99\u2c9b\u2c9d\u2c9f\u2ca1\u2ca3\u2ca5\u2ca7\u2ca9\u2cab\u2cad\u2caf\u2cb1\u2cb3\u2cb5\u2cb7\u2cb9\u2cbb\u2cbd\u2cbf\u2cc1\u2cc3\u2cc5\u2cc7\u2cc9\u2ccb\u2ccd\u2ccf\u2cd1\u2cd3\u2cd5\u2cd7\u2cd9\u2cdb\u2cdd\u2cdf\u2ce1\u2ce3\u2ce4\u2d00\u2d01\u2d02\u2d03\u2d04\u2d05\u2d06\u2d07\u2d08\u2d09\u2d0a\u2d0b\u2d0c\u2d0d\u2d0e\u2d0f\u2d10\u2d11\u2d12\u2d13\u2d14\u2d15\u2d16\u2d17\u2d18\u2d19\u2d1a\u2d1b\u2d1c\u2d1d\u2d1e\u2d1f\u2d20\u2d21\u2d22\u2d23\u2d24\u2d25\ufb00\ufb01\ufb02\ufb03\ufb04\ufb05\ufb06\ufb13\ufb14\ufb15\ufb16\ufb17\uff41\uff42\uff43\uff44\uff45\uff46\uff47\uff48\uff49\uff4a\uff4b\uff4c\uff4d\uff4e\uff4f\uff50\uff51\uff52\uff53\uff54\uff55\uff56\uff57\uff58\uff59\uff5a'
+
+Lm = u'\u02b0\u02b1\u02b2\u02b3\u02b4\u02b5\u02b6\u02b7\u02b8\u02b9\u02ba\u02bb\u02bc\u02bd\u02be\u02bf\u02c0\u02c1\u02c6\u02c7\u02c8\u02c9\u02ca\u02cb\u02cc\u02cd\u02ce\u02cf\u02d0\u02d1\u02e0\u02e1\u02e2\u02e3\u02e4\u02ee\u037a\u0559\u0640\u06e5\u06e6\u0e46\u0ec6\u10fc\u17d7\u1843\u1d2c\u1d2d\u1d2e\u1d2f\u1d30\u1d31\u1d32\u1d33\u1d34\u1d35\u1d36\u1d37\u1d38\u1d39\u1d3a\u1d3b\u1d3c\u1d3d\u1d3e\u1d3f\u1d40\u1d41\u1d42\u1d43\u1d44\u1d45\u1d46\u1d47\u1d48\u1d49\u1d4a\u1d4b\u1d4c\u1d4d\u1d4e\u1d4f\u1d50\u1d51\u1d52\u1d53\u1d54\u1d55\u1d56\u1d57\u1d58\u1d59\u1d5a\u1d5b\u1d5c\u1d5d\u1d5e\u1d5f\u1d60\u1d61\u1d78\u1d9b\u1d9c\u1d9d\u1d9e\u1d9f\u1da0\u1da1\u1da2\u1da3\u1da4\u1da5\u1da6\u1da7\u1da8\u1da9\u1daa\u1dab\u1dac\u1dad\u1dae\u1daf\u1db0\u1db1\u1db2\u1db3\u1db4\u1db5\u1db6\u1db7\u1db8\u1db9\u1dba\u1dbb\u1dbc\u1dbd\u1dbe\u1dbf\u2090\u2091\u2092\u2093\u2094\u2d6f\u3005\u3031\u3032\u3033\u3034\u3035\u303b\u309d\u309e\u30fc\u30fd\u30fe\ua015\uff70\uff9e\uff9f'
+
+Lo = u'\u01bb\u01c0\u01c1\u01c2\u01c3\u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7\u05d8\u05d9\u05da\u05db\u05dc\u05dd\u05de\u05df\u05e0\u05e1\u05e2\u05e3\u05e4\u05e5\u05e6\u05e7\u05e8\u05e9\u05ea\u05f0\u05f1\u05f2\u0621\u0622\u0623\u0624\u0625\u0626\u0627\u0628\u0629\u062a\u062b\u062c\u062d\u062e\u062f\u0630\u0631\u0632\u0633\u0634\u0635\u0636\u0637\u0638\u0639\u063a\u0641\u0642\u0643\u0644\u0645\u0646\u0647\u0648\u0649\u064a\u066e\u066f\u0671\u0672\u0673\u0674\u0675\u0676\u0677\u0678\u0679\u067a\u067b\u067c\u067d\u067e\u067f\u0680\u0681\u0682\u0683\u0684\u0685\u0686\u0687\u0688\u0689\u068a\u068b\u068c\u068d\u068e\u068f\u0690\u0691\u0692\u0693\u0694\u0695\u0696\u0697\u0698\u0699\u069a\u069b\u069c\u069d\u069e\u069f\u06a0\u06a1\u06a2\u06a3\u06a4\u06a5\u06a6\u06a7\u06a8\u06a9\u06aa\u06ab\u06ac\u06ad\u06ae\u06af\u06b0\u06b1\u06b2\u06b3\u06b4\u06b5\u06b6\u06b7\u06b8\u06b9\u06ba\u06bb\u06bc\u06bd\u06be\u06bf\u06c0\u06c1\u06c2\u06c3\u06c4\u06c5\u06c6\u06c7\u06c8\u06c9\u06ca\u06cb\u06cc\u06cd\u06ce\u06cf\u06d0\u06d1\u06d2\u06d3\u06d5\u06ee\u06ef\u06fa\u06fb\u06fc\u06ff\u0710\u0712\u0713\u0714\u0715\u0716\u0717\u0718\u0719\u071a\u071b\u071c\u071d\u071e\u071f\u0720\u0721\u0722\u0723\u0724\u0725\u0726\u0727\u0728\u0729\u072a\u072b\u072c\u072d\u072e\u072f\u074d\u074e\u074f\u0750\u0751\u0752\u0753\u0754\u0755\u0756\u0757\u0758\u0759\u075a\u075b\u075c\u075d\u075e\u075f\u0760\u0761\u0762\u0763\u0764\u0765\u0766\u0767\u0768\u0769\u076a\u076b\u076c\u076d\u0780\u0781\u0782\u0783\u0784\u0785\u0786\u0787\u0788\u0789\u078a\u078b\u078c\u078d\u078e\u078f\u0790\u0791\u0792\u0793\u0794\u0795\u0796\u0797\u0798\u0799\u079a\u079b\u079c\u079d\u079e\u079f\u07a0\u07a1\u07a2\u07a3\u07a4\u07a5\u07b1\u0904\u0905\u0906\u0907\u0908\u0909\u090a\u090b\u090c\u090d\u090e\u090f\u0910\u0911\u0912\u0913\u0914\u0915\u0916\u0917\u0918\u0919\u091a\u091b\u091c\u091d\u091e\u091f\u0920\u0921\u0922\u0923\u0924\u0925\u0926\u0927\u0928\u0929\u092a\u092b\u092c\u092d\u092e\u092f\u0930\u0931\u0932\u0933\u0934\u0935\u0936\u0937\u0938\u0939\u093d\u0950\u0958\u0959\u095a\u095b\u095c\u095d\u095e\u095f\u0960\u0961\u097d\u0985\u0986\u0987\u0988\u0989\u098a\u098b\u098c\u098f\u0990\u0993\u0994\u0995\u0996\u0997\u0998\u0999\u099a\u099b\u099c\u099d\u099e\u099f\u09a0\u09a1\u09a2\u09a3\u09a4\u09a5\u09a6\u09a7\u09a8\u09aa\u09ab\u09ac\u09ad\u09ae\u09af\u09b0\u09b2\u09b6\u09b7\u09b8\u09b9\u09bd\u09ce\u09dc\u09dd\u09df\u09e0\u09e1\u09f0\u09f1\u0a05\u0a06\u0a07\u0a08\u0a09\u0a0a\u0a0f\u0a10\u0a13\u0a14\u0a15\u0a16\u0a17\u0a18\u0a19\u0a1a\u0a1b\u0a1c\u0a1d\u0a1e\u0a1f\u0a20\u0a21\u0a22\u0a23\u0a24\u0a25\u0a26\u0a27\u0a28\u0a2a\u0a2b\u0a2c\u0a2d\u0a2e\u0a2f\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59\u0a5a\u0a5b\u0a5c\u0a5e\u0a72\u0a73\u0a74\u0a85\u0a86\u0a87\u0a88\u0a89\u0a8a\u0a8b\u0a8c\u0a8d\u0a8f\u0a90\u0a91\u0a93\u0a94\u0a95\u0a96\u0a97\u0a98\u0a99\u0a9a\u0a9b\u0a9c\u0a9d\u0a9e\u0a9f\u0aa0\u0aa1\u0aa2\u0aa3\u0aa4\u0aa5\u0aa6\u0aa7\u0aa8\u0aaa\u0aab\u0aac\u0aad\u0aae\u0aaf\u0ab0\u0ab2\u0ab3\u0ab5\u0ab6\u0ab7\u0ab8\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05\u0b06\u0b07\u0b08\u0b09\u0b0a\u0b0b\u0b0c\u0b0f\u0b10\u0b13\u0b14\u0b15\u0b16\u0b17\u0b18\u0b19\u0b1a\u0b1b\u0b1c\u0b1d\u0b1e\u0b1f\u0b20\u0b21\u0b22\u0b23\u0b24\u0b25\u0b26\u0b27\u0b28\u0b2a\u0b2b\u0b2c\u0b2d\u0b2e\u0b2f\u0b30\u0b32\u0b33\u0b35\u0b36\u0b37\u0b38\u0b39\u0b3d\u0b5c\u0b5d\u0b5f\u0b60\u0b61\u0b71\u0b83\u0b85\u0b86\u0b87\u0b88\u0b89\u0b8a\u0b8e\u0b8f\u0b90\u0b92\u0b93\u0b94\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8\u0ba9\u0baa\u0bae\u0baf\u0bb0\u0bb1\u0bb2\u0bb3\u0bb4\u0bb5\u0bb6\u0bb7\u0bb8\u0bb9\u0c05\u0c06\u0c07\u0c08\u0c09\u0c0a\u0c0b\u0c0c\u0c0e\u0c0f\u0c10\u0c12\u0c13\u0c14\u0c15\u0c16\u0c17\u0c18\u0c19\u0c1a\u0c1b\u0c1c\u0c1d\u0c1e\u0c1f\u0c20\u0c21\u0c22\u0c23\u0c24\u0c25\u0c26\u0c27\u0c28\u0c2a\u0c2b\u0c2c\u0c2d\u0c2e\u0c2f\u0c30\u0c31\u0c32\u0c33\u0c35\u0c36\u0c37\u0c38\u0c39\u0c60\u0c61\u0c85\u0c86\u0c87\u0c88\u0c89\u0c8a\u0c8b\u0c8c\u0c8e\u0c8f\u0c90\u0c92\u0c93\u0c94\u0c95\u0c96\u0c97\u0c98\u0c99\u0c9a\u0c9b\u0c9c\u0c9d\u0c9e\u0c9f\u0ca0\u0ca1\u0ca2\u0ca3\u0ca4\u0ca5\u0ca6\u0ca7\u0ca8\u0caa\u0cab\u0cac\u0cad\u0cae\u0caf\u0cb0\u0cb1\u0cb2\u0cb3\u0cb5\u0cb6\u0cb7\u0cb8\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0d05\u0d06\u0d07\u0d08\u0d09\u0d0a\u0d0b\u0d0c\u0d0e\u0d0f\u0d10\u0d12\u0d13\u0d14\u0d15\u0d16\u0d17\u0d18\u0d19\u0d1a\u0d1b\u0d1c\u0d1d\u0d1e\u0d1f\u0d20\u0d21\u0d22\u0d23\u0d24\u0d25\u0d26\u0d27\u0d28\u0d2a\u0d2b\u0d2c\u0d2d\u0d2e\u0d2f\u0d30\u0d31\u0d32\u0d33\u0d34\u0d35\u0d36\u0d37\u0d38\u0d39\u0d60\u0d61\u0d85\u0d86\u0d87\u0d88\u0d89\u0d8a\u0d8b\u0d8c\u0d8d\u0d8e\u0d8f\u0d90\u0d91\u0d92\u0d93\u0d94\u0d95\u0d96\u0d9a\u0d9b\u0d9c\u0d9d\u0d9e\u0d9f\u0da0\u0da1\u0da2\u0da3\u0da4\u0da5\u0da6\u0da7\u0da8\u0da9\u0daa\u0dab\u0dac\u0dad\u0dae\u0daf\u0db0\u0db1\u0db3\u0db4\u0db5\u0db6\u0db7\u0db8\u0db9\u0dba\u0dbb\u0dbd\u0dc0\u0dc1\u0dc2\u0dc3\u0dc4\u0dc5\u0dc6\u0e01\u0e02\u0e03\u0e04\u0e05\u0e06\u0e07\u0e08\u0e09\u0e0a\u0e0b\u0e0c\u0e0d\u0e0e\u0e0f\u0e10\u0e11\u0e12\u0e13\u0e14\u0e15\u0e16\u0e17\u0e18\u0e19\u0e1a\u0e1b\u0e1c\u0e1d\u0e1e\u0e1f\u0e20\u0e21\u0e22\u0e23\u0e24\u0e25\u0e26\u0e27\u0e28\u0e29\u0e2a\u0e2b\u0e2c\u0e2d\u0e2e\u0e2f\u0e30\u0e32\u0e33\u0e40\u0e41\u0e42\u0e43\u0e44\u0e45\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94\u0e95\u0e96\u0e97\u0e99\u0e9a\u0e9b\u0e9c\u0e9d\u0e9e\u0e9f\u0ea1\u0ea2\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead\u0eae\u0eaf\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0\u0ec1\u0ec2\u0ec3\u0ec4\u0edc\u0edd\u0f00\u0f40\u0f41\u0f42\u0f43\u0f44\u0f45\u0f46\u0f47\u0f49\u0f4a\u0f4b\u0f4c\u0f4d\u0f4e\u0f4f\u0f50\u0f51\u0f52\u0f53\u0f54\u0f55\u0f56\u0f57\u0f58\u0f59\u0f5a\u0f5b\u0f5c\u0f5d\u0f5e\u0f5f\u0f60\u0f61\u0f62\u0f63\u0f64\u0f65\u0f66\u0f67\u0f68\u0f69\u0f6a\u0f88\u0f89\u0f8a\u0f8b\u1000\u1001\u1002\u1003\u1004\u1005\u1006\u1007\u1008\u1009\u100a\u100b\u100c\u100d\u100e\u100f\u1010\u1011\u1012\u1013\u1014\u1015\u1016\u1017\u1018\u1019\u101a\u101b\u101c\u101d\u101e\u101f\u1020\u1021\u1023\u1024\u1025\u1026\u1027\u1029\u102a\u1050\u1051\u1052\u1053\u1054\u1055\u10d0\u10d1\u10d2\u10d3\u10d4\u10d5\u10d6\u10d7\u10d8\u10d9\u10da\u10db\u10dc\u10dd\u10de\u10df\u10e0\u10e1\u10e2\u10e3\u10e4\u10e5\u10e6\u10e7\u10e8\u10e9\u10ea\u10eb\u10ec\u10ed\u10ee\u10ef\u10f0\u10f1\u10f2\u10f3\u10f4\u10f5\u10f6\u10f7\u10f8\u10f9\u10fa\u1100\u1101\u1102\u1103\u1104\u1105\u1106\u1107\u1108\u1109\u110a\u110b\u110c\u110d\u110e\u110f\u1110\u1111\u1112\u1113\u1114\u1115\u1116\u1117\u1118\u1119\u111a\u111b\u111c\u111d\u111e\u111f\u1120\u1121\u1122\u1123\u1124\u1125\u1126\u1127\u1128\u1129\u112a\u112b\u112c\u112d\u112e\u112f\u1130\u1131\u1132\u1133\u1134\u1135\u1136\u1137\u1138\u1139\u113a\u113b\u113c\u113d\u113e\u113f\u1140\u1141\u1142\u1143\u1144\u1145\u1146\u1147\u1148\u1149\u114a\u114b\u114c\u114d\u114e\u114f\u1150\u1151\u1152\u1153\u1154\u1155\u1156\u1157\u1158\u1159\u115f\u1160\u1161\u1162\u1163\u1164\u1165\u1166\u1167\u1168\u1169\u116a\u116b\u116c\u116d\u116e\u116f\u1170\u1171\u1172\u1173\u1174\u1175\u1176\u1177\u1178\u1179\u117a\u117b\u117c\u117d\u117e\u117f\u1180\u1181\u1182\u1183\u1184\u1185\u1186\u1187\u1188\u1189\u118a\u118b\u118c\u118d\u118e\u118f\u1190\u1191\u1192\u1193\u1194\u1195\u1196\u1197\u1198\u1199\u119a\u119b\u119c\u119d\u119e\u119f\u11a0\u11a1\u11a2\u11a8\u11a9\u11aa\u11ab\u11ac\u11ad\u11ae\u11af\u11b0\u11b1\u11b2\u11b3\u11b4\u11b5\u11b6\u11b7\u11b8\u11b9\u11ba\u11bb\u11bc\u11bd\u11be\u11bf\u11c0\u11c1\u11c2\u11c3\u11c4\u11c5\u11c6\u11c7\u11c8\u11c9\u11ca\u11cb\u11cc\u11cd\u11ce\u11cf\u11d0\u11d1\u11d2\u11d3\u11d4\u11d5\u11d6\u11d7\u11d8\u11d9\u11da\u11db\u11dc\u11dd\u11de\u11df\u11e0\u11e1\u11e2\u11e3\u11e4\u11e5\u11e6\u11e7\u11e8\u11e9\u11ea\u11eb\u11ec\u11ed\u11ee\u11ef\u11f0\u11f1\u11f2\u11f3\u11f4\u11f5\u11f6\u11f7\u11f8\u11f9\u1200\u1201\u1202\u1203\u1204\u1205\u1206\u1207\u1208\u1209\u120a\u120b\u120c\u120d\u120e\u120f\u1210\u1211\u1212\u1213\u1214\u1215\u1216\u1217\u1218\u1219\u121a\u121b\u121c\u121d\u121e\u121f\u1220\u1221\u1222\u1223\u1224\u1225\u1226\u1227\u1228\u1229\u122a\u122b\u122c\u122d\u122e\u122f\u1230\u1231\u1232\u1233\u1234\u1235\u1236\u1237\u1238\u1239\u123a\u123b\u123c\u123d\u123e\u123f\u1240\u1241\u1242\u1243\u1244\u1245\u1246\u1247\u1248\u124a\u124b\u124c\u124d\u1250\u1251\u1252\u1253\u1254\u1255\u1256\u1258\u125a\u125b\u125c\u125d\u1260\u1261\u1262\u1263\u1264\u1265\u1266\u1267\u1268\u1269\u126a\u126b\u126c\u126d\u126e\u126f\u1270\u1271\u1272\u1273\u1274\u1275\u1276\u1277\u1278\u1279\u127a\u127b\u127c\u127d\u127e\u127f\u1280\u1281\u1282\u1283\u1284\u1285\u1286\u1287\u1288\u128a\u128b\u128c\u128d\u1290\u1291\u1292\u1293\u1294\u1295\u1296\u1297\u1298\u1299\u129a\u129b\u129c\u129d\u129e\u129f\u12a0\u12a1\u12a2\u12a3\u12a4\u12a5\u12a6\u12a7\u12a8\u12a9\u12aa\u12ab\u12ac\u12ad\u12ae\u12af\u12b0\u12b2\u12b3\u12b4\u12b5\u12b8\u12b9\u12ba\u12bb\u12bc\u12bd\u12be\u12c0\u12c2\u12c3\u12c4\u12c5\u12c8\u12c9\u12ca\u12cb\u12cc\u12cd\u12ce\u12cf\u12d0\u12d1\u12d2\u12d3\u12d4\u12d5\u12d6\u12d8\u12d9\u12da\u12db\u12dc\u12dd\u12de\u12df\u12e0\u12e1\u12e2\u12e3\u12e4\u12e5\u12e6\u12e7\u12e8\u12e9\u12ea\u12eb\u12ec\u12ed\u12ee\u12ef\u12f0\u12f1\u12f2\u12f3\u12f4\u12f5\u12f6\u12f7\u12f8\u12f9\u12fa\u12fb\u12fc\u12fd\u12fe\u12ff\u1300\u1301\u1302\u1303\u1304\u1305\u1306\u1307\u1308\u1309\u130a\u130b\u130c\u130d\u130e\u130f\u1310\u1312\u1313\u1314\u1315\u1318\u1319\u131a\u131b\u131c\u131d\u131e\u131f\u1320\u1321\u1322\u1323\u1324\u1325\u1326\u1327\u1328\u1329\u132a\u132b\u132c\u132d\u132e\u132f\u1330\u1331\u1332\u1333\u1334\u1335\u1336\u1337\u1338\u1339\u133a\u133b\u133c\u133d\u133e\u133f\u1340\u1341\u1342\u1343\u1344\u1345\u1346\u1347\u1348\u1349\u134a\u134b\u134c\u134d\u134e\u134f\u1350\u1351\u1352\u1353\u1354\u1355\u1356\u1357\u1358\u1359\u135a\u1380\u1381\u1382\u1383\u1384\u1385\u1386\u1387\u1388\u1389\u138a\u138b\u138c\u138d\u138e\u138f\u13a0\u13a1\u13a2\u13a3\u13a4\u13a5\u13a6\u13a7\u13a8\u13a9\u13aa\u13ab\u13ac\u13ad\u13ae\u13af\u13b0\u13b1\u13b2\u13b3\u13b4\u13b5\u13b6\u13b7\u13b8\u13b9\u13ba\u13bb\u13bc\u13bd\u13be\u13bf\u13c0\u13c1\u13c2\u13c3\u13c4\u13c5\u13c6\u13c7\u13c8\u13c9\u13ca\u13cb\u13cc\u13cd\u13ce\u13cf\u13d0\u13d1\u13d2\u13d3\u13d4\u13d5\u13d6\u13d7\u13d8\u13d9\u13da\u13db\u13dc\u13dd\u13de\u13df\u13e0\u13e1\u13e2\u13e3\u13e4\u13e5\u13e6\u13e7\u13e8\u13e9\u13ea\u13eb\u13ec\u13ed\u13ee\u13ef\u13f0\u13f1\u13f2\u13f3\u13f4\u1401\u1402\u1403\u1404\u1405\u1406\u1407\u1408\u1409\u140a\u140b\u140c\u140d\u140e\u140f\u1410\u1411\u1412\u1413\u1414\u1415\u1416\u1417\u1418\u1419\u141a\u141b\u141c\u141d\u141e\u141f\u1420\u1421\u1422\u1423\u1424\u1425\u1426\u1427\u1428\u1429\u142a\u142b\u142c\u142d\u142e\u142f\u1430\u1431\u1432\u1433\u1434\u1435\u1436\u1437\u1438\u1439\u143a\u143b\u143c\u143d\u143e\u143f\u1440\u1441\u1442\u1443\u1444\u1445\u1446\u1447\u1448\u1449\u144a\u144b\u144c\u144d\u144e\u144f\u1450\u1451\u1452\u1453\u1454\u1455\u1456\u1457\u1458\u1459\u145a\u145b\u145c\u145d\u145e\u145f\u1460\u1461\u1462\u1463\u1464\u1465\u1466\u1467\u1468\u1469\u146a\u146b\u146c\u146d\u146e\u146f\u1470\u1471\u1472\u1473\u1474\u1475\u1476\u1477\u1478\u1479\u147a\u147b\u147c\u147d\u147e\u147f\u1480\u1481\u1482\u1483\u1484\u1485\u1486\u1487\u1488\u1489\u148a\u148b\u148c\u148d\u148e\u148f\u1490\u1491\u1492\u1493\u1494\u1495\u1496\u1497\u1498\u1499\u149a\u149b\u149c\u149d\u149e\u149f\u14a0\u14a1\u14a2\u14a3\u14a4\u14a5\u14a6\u14a7\u14a8\u14a9\u14aa\u14ab\u14ac\u14ad\u14ae\u14af\u14b0\u14b1\u14b2\u14b3\u14b4\u14b5\u14b6\u14b7\u14b8\u14b9\u14ba\u14bb\u14bc\u14bd\u14be\u14bf\u14c0\u14c1\u14c2\u14c3\u14c4\u14c5\u14c6\u14c7\u14c8\u14c9\u14ca\u14cb\u14cc\u14cd\u14ce\u14cf\u14d0\u14d1\u14d2\u14d3\u14d4\u14d5\u14d6\u14d7\u14d8\u14d9\u14da\u14db\u14dc\u14dd\u14de\u14df\u14e0\u14e1\u14e2\u14e3\u14e4\u14e5\u14e6\u14e7\u14e8\u14e9\u14ea\u14eb\u14ec\u14ed\u14ee\u14ef\u14f0\u14f1\u14f2\u14f3\u14f4\u14f5\u14f6\u14f7\u14f8\u14f9\u14fa\u14fb\u14fc\u14fd\u14fe\u14ff\u1500\u1501\u1502\u1503\u1504\u1505\u1506\u1507\u1508\u1509\u150a\u150b\u150c\u150d\u150e\u150f\u1510\u1511\u1512\u1513\u1514\u1515\u1516\u1517\u1518\u1519\u151a\u151b\u151c\u151d\u151e\u151f\u1520\u1521\u1522\u1523\u1524\u1525\u1526\u1527\u1528\u1529\u152a\u152b\u152c\u152d\u152e\u152f\u1530\u1531\u1532\u1533\u1534\u1535\u1536\u1537\u1538\u1539\u153a\u153b\u153c\u153d\u153e\u153f\u1540\u1541\u1542\u1543\u1544\u1545\u1546\u1547\u1548\u1549\u154a\u154b\u154c\u154d\u154e\u154f\u1550\u1551\u1552\u1553\u1554\u1555\u1556\u1557\u1558\u1559\u155a\u155b\u155c\u155d\u155e\u155f\u1560\u1561\u1562\u1563\u1564\u1565\u1566\u1567\u1568\u1569\u156a\u156b\u156c\u156d\u156e\u156f\u1570\u1571\u1572\u1573\u1574\u1575\u1576\u1577\u1578\u1579\u157a\u157b\u157c\u157d\u157e\u157f\u1580\u1581\u1582\u1583\u1584\u1585\u1586\u1587\u1588\u1589\u158a\u158b\u158c\u158d\u158e\u158f\u1590\u1591\u1592\u1593\u1594\u1595\u1596\u1597\u1598\u1599\u159a\u159b\u159c\u159d\u159e\u159f\u15a0\u15a1\u15a2\u15a3\u15a4\u15a5\u15a6\u15a7\u15a8\u15a9\u15aa\u15ab\u15ac\u15ad\u15ae\u15af\u15b0\u15b1\u15b2\u15b3\u15b4\u15b5\u15b6\u15b7\u15b8\u15b9\u15ba\u15bb\u15bc\u15bd\u15be\u15bf\u15c0\u15c1\u15c2\u15c3\u15c4\u15c5\u15c6\u15c7\u15c8\u15c9\u15ca\u15cb\u15cc\u15cd\u15ce\u15cf\u15d0\u15d1\u15d2\u15d3\u15d4\u15d5\u15d6\u15d7\u15d8\u15d9\u15da\u15db\u15dc\u15dd\u15de\u15df\u15e0\u15e1\u15e2\u15e3\u15e4\u15e5\u15e6\u15e7\u15e8\u15e9\u15ea\u15eb\u15ec\u15ed\u15ee\u15ef\u15f0\u15f1\u15f2\u15f3\u15f4\u15f5\u15f6\u15f7\u15f8\u15f9\u15fa\u15fb\u15fc\u15fd\u15fe\u15ff\u1600\u1601\u1602\u1603\u1604\u1605\u1606\u1607\u1608\u1609\u160a\u160b\u160c\u160d\u160e\u160f\u1610\u1611\u1612\u1613\u1614\u1615\u1616\u1617\u1618\u1619\u161a\u161b\u161c\u161d\u161e\u161f\u1620\u1621\u1622\u1623\u1624\u1625\u1626\u1627\u1628\u1629\u162a\u162b\u162c\u162d\u162e\u162f\u1630\u1631\u1632\u1633\u1634\u1635\u1636\u1637\u1638\u1639\u163a\u163b\u163c\u163d\u163e\u163f\u1640\u1641\u1642\u1643\u1644\u1645\u1646\u1647\u1648\u1649\u164a\u164b\u164c\u164d\u164e\u164f\u1650\u1651\u1652\u1653\u1654\u1655\u1656\u1657\u1658\u1659\u165a\u165b\u165c\u165d\u165e\u165f\u1660\u1661\u1662\u1663\u1664\u1665\u1666\u1667\u1668\u1669\u166a\u166b\u166c\u166f\u1670\u1671\u1672\u1673\u1674\u1675\u1676\u1681\u1682\u1683\u1684\u1685\u1686\u1687\u1688\u1689\u168a\u168b\u168c\u168d\u168e\u168f\u1690\u1691\u1692\u1693\u1694\u1695\u1696\u1697\u1698\u1699\u169a\u16a0\u16a1\u16a2\u16a3\u16a4\u16a5\u16a6\u16a7\u16a8\u16a9\u16aa\u16ab\u16ac\u16ad\u16ae\u16af\u16b0\u16b1\u16b2\u16b3\u16b4\u16b5\u16b6\u16b7\u16b8\u16b9\u16ba\u16bb\u16bc\u16bd\u16be\u16bf\u16c0\u16c1\u16c2\u16c3\u16c4\u16c5\u16c6\u16c7\u16c8\u16c9\u16ca\u16cb\u16cc\u16cd\u16ce\u16cf\u16d0\u16d1\u16d2\u16d3\u16d4\u16d5\u16d6\u16d7\u16d8\u16d9\u16da\u16db\u16dc\u16dd\u16de\u16df\u16e0\u16e1\u16e2\u16e3\u16e4\u16e5\u16e6\u16e7\u16e8\u16e9\u16ea\u1700\u1701\u1702\u1703\u1704\u1705\u1706\u1707\u1708\u1709\u170a\u170b\u170c\u170e\u170f\u1710\u1711\u1720\u1721\u1722\u1723\u1724\u1725\u1726\u1727\u1728\u1729\u172a\u172b\u172c\u172d\u172e\u172f\u1730\u1731\u1740\u1741\u1742\u1743\u1744\u1745\u1746\u1747\u1748\u1749\u174a\u174b\u174c\u174d\u174e\u174f\u1750\u1751\u1760\u1761\u1762\u1763\u1764\u1765\u1766\u1767\u1768\u1769\u176a\u176b\u176c\u176e\u176f\u1770\u1780\u1781\u1782\u1783\u1784\u1785\u1786\u1787\u1788\u1789\u178a\u178b\u178c\u178d\u178e\u178f\u1790\u1791\u1792\u1793\u1794\u1795\u1796\u1797\u1798\u1799\u179a\u179b\u179c\u179d\u179e\u179f\u17a0\u17a1\u17a2\u17a3\u17a4\u17a5\u17a6\u17a7\u17a8\u17a9\u17aa\u17ab\u17ac\u17ad\u17ae\u17af\u17b0\u17b1\u17b2\u17b3\u17dc\u1820\u1821\u1822\u1823\u1824\u1825\u1826\u1827\u1828\u1829\u182a\u182b\u182c\u182d\u182e\u182f\u1830\u1831\u1832\u1833\u1834\u1835\u1836\u1837\u1838\u1839\u183a\u183b\u183c\u183d\u183e\u183f\u1840\u1841\u1842\u1844\u1845\u1846\u1847\u1848\u1849\u184a\u184b\u184c\u184d\u184e\u184f\u1850\u1851\u1852\u1853\u1854\u1855\u1856\u1857\u1858\u1859\u185a\u185b\u185c\u185d\u185e\u185f\u1860\u1861\u1862\u1863\u1864\u1865\u1866\u1867\u1868\u1869\u186a\u186b\u186c\u186d\u186e\u186f\u1870\u1871\u1872\u1873\u1874\u1875\u1876\u1877\u1880\u1881\u1882\u1883\u1884\u1885\u1886\u1887\u1888\u1889\u188a\u188b\u188c\u188d\u188e\u188f\u1890\u1891\u1892\u1893\u1894\u1895\u1896\u1897\u1898\u1899\u189a\u189b\u189c\u189d\u189e\u189f\u18a0\u18a1\u18a2\u18a3\u18a4\u18a5\u18a6\u18a7\u18a8\u1900\u1901\u1902\u1903\u1904\u1905\u1906\u1907\u1908\u1909\u190a\u190b\u190c\u190d\u190e\u190f\u1910\u1911\u1912\u1913\u1914\u1915\u1916\u1917\u1918\u1919\u191a\u191b\u191c\u1950\u1951\u1952\u1953\u1954\u1955\u1956\u1957\u1958\u1959\u195a\u195b\u195c\u195d\u195e\u195f\u1960\u1961\u1962\u1963\u1964\u1965\u1966\u1967\u1968\u1969\u196a\u196b\u196c\u196d\u1970\u1971\u1972\u1973\u1974\u1980\u1981\u1982\u1983\u1984\u1985\u1986\u1987\u1988\u1989\u198a\u198b\u198c\u198d\u198e\u198f\u1990\u1991\u1992\u1993\u1994\u1995\u1996\u1997\u1998\u1999\u199a\u199b\u199c\u199d\u199e\u199f\u19a0\u19a1\u19a2\u19a3\u19a4\u19a5\u19a6\u19a7\u19a8\u19a9\u19c1\u19c2\u19c3\u19c4\u19c5\u19c6\u19c7\u1a00\u1a01\u1a02\u1a03\u1a04\u1a05\u1a06\u1a07\u1a08\u1a09\u1a0a\u1a0b\u1a0c\u1a0d\u1a0e\u1a0f\u1a10\u1a11\u1a12\u1a13\u1a14\u1a15\u1a16\u2135\u2136\u2137\u2138\u2d30\u2d31\u2d32\u2d33\u2d34\u2d35\u2d36\u2d37\u2d38\u2d39\u2d3a\u2d3b\u2d3c\u2d3d\u2d3e\u2d3f\u2d40\u2d41\u2d42\u2d43\u2d44\u2d45\u2d46\u2d47\u2d48\u2d49\u2d4a\u2d4b\u2d4c\u2d4d\u2d4e\u2d4f\u2d50\u2d51\u2d52\u2d53\u2d54\u2d55\u2d56\u2d57\u2d58\u2d59\u2d5a\u2d5b\u2d5c\u2d5d\u2d5e\u2d5f\u2d60\u2d61\u2d62\u2d63\u2d64\u2d65\u2d80\u2d81\u2d82\u2d83\u2d84\u2d85\u2d86\u2d87\u2d88\u2d89\u2d8a\u2d8b\u2d8c\u2d8d\u2d8e\u2d8f\u2d90\u2d91\u2d92\u2d93\u2d94\u2d95\u2d96\u2da0\u2da1\u2da2\u2da3\u2da4\u2da5\u2da6\u2da8\u2da9\u2daa\u2dab\u2dac\u2dad\u2dae\u2db0\u2db1\u2db2\u2db3\u2db4\u2db5\u2db6\u2db8\u2db9\u2dba\u2dbb\u2dbc\u2dbd\u2dbe\u2dc0\u2dc1\u2dc2\u2dc3\u2dc4\u2dc5\u2dc6\u2dc8\u2dc9\u2dca\u2dcb\u2dcc\u2dcd\u2dce\u2dd0\u2dd1\u2dd2\u2dd3\u2dd4\u2dd5\u2dd6\u2dd8\u2dd9\u2dda\u2ddb\u2ddc\u2ddd\u2dde\u3006\u303c\u3041\u3042\u3043\u3044\u3045\u3046\u3047\u3048\u3049\u304a\u304b\u304c\u304d\u304e\u304f\u3050\u3051\u3052\u3053\u3054\u3055\u3056\u3057\u3058\u3059\u305a\u305b\u305c\u305d\u305e\u305f\u3060\u3061\u3062\u3063\u3064\u3065\u3066\u3067\u3068\u3069\u306a\u306b\u306c\u306d\u306e\u306f\u3070\u3071\u3072\u3073\u3074\u3075\u3076\u3077\u3078\u3079\u307a\u307b\u307c\u307d\u307e\u307f\u3080\u3081\u3082\u3083\u3084\u3085\u3086\u3087\u3088\u3089\u308a\u308b\u308c\u308d\u308e\u308f\u3090\u3091\u3092\u3093\u3094\u3095\u3096\u309f\u30a1\u30a2\u30a3\u30a4\u30a5\u30a6\u30a7\u30a8\u30a9\u30aa\u30ab\u30ac\u30ad\u30ae\u30af\u30b0\u30b1\u30b2\u30b3\u30b4\u30b5\u30b6\u30b7\u30b8\u30b9\u30ba\u30bb\u30bc\u30bd\u30be\u30bf\u30c0\u30c1\u30c2\u30c3\u30c4\u30c5\u30c6\u30c7\u30c8\u30c9\u30ca\u30cb\u30cc\u30cd\u30ce\u30cf\u30d0\u30d1\u30d2\u30d3\u30d4\u30d5\u30d6\u30d7\u30d8\u30d9\u30da\u30db\u30dc\u30dd\u30de\u30df\u30e0\u30e1\u30e2\u30e3\u30e4\u30e5\u30e6\u30e7\u30e8\u30e9\u30ea\u30eb\u30ec\u30ed\u30ee\u30ef\u30f0\u30f1\u30f2\u30f3\u30f4\u30f5\u30f6\u30f7\u30f8\u30f9\u30fa\u30ff\u3105\u3106\u3107\u3108\u3109\u310a\u310b\u310c\u310d\u310e\u310f\u3110\u3111\u3112\u3113\u3114\u3115\u3116\u3117\u3118\u3119\u311a\u311b\u311c\u311d\u311e\u311f\u3120\u3121\u3122\u3123\u3124\u3125\u3126\u3127\u3128\u3129\u312a\u312b\u312c\u3131\u3132\u3133\u3134\u3135\u3136\u3137\u3138\u3139\u313a\u313b\u313c\u313d\u313e\u313f\u3140\u3141\u3142\u3143\u3144\u3145\u3146\u3147\u3148\u3149\u314a\u314b\u314c\u314d\u314e\u314f\u3150\u3151\u3152\u3153\u3154\u3155\u3156\u3157\u3158\u3159\u315a\u315b\u315c\u315d\u315e\u315f\u3160\u3161\u3162\u3163\u3164\u3165\u3166\u3167\u3168\u3169\u316a\u316b\u316c\u316d\u316e\u316f\u3170\u3171\u3172\u3173\u3174\u3175\u3176\u3177\u3178\u3179\u317a\u317b\u317c\u317d\u317e\u317f\u3180\u3181\u3182\u3183\u3184\u3185\u3186\u3187\u3188\u3189\u318a\u318b\u318c\u318d\u318e\u31a0\u31a1\u31a2\u31a3\u31a4\u31a5\u31a6\u31a7\u31a8\u31a9\u31aa\u31ab\u31ac\u31ad\u31ae\u31af\u31b0\u31b1\u31b2\u31b3\u31b4\u31b5\u31b6\u31b7\u31f0\u31f1\u31f2\u31f3\u31f4\u31f5\u31f6\u31f7\u31f8\u31f9\u31fa\u31fb\u31fc\u31fd\u31fe\u31ff\u3400\u3401\u3402\u3403\u3404\u3405\u3406\u3407\u3408\u3409\u340a\u340b\u340c\u340d\u340e\u340f\u3410\u3411\u3412\u3413\u3414\u3415\u3416\u3417\u3418\u3419\u341a\u341b\u341c\u341d\u341e\u341f\u3420\u3421\u3422\u3423\u3424\u3425\u3426\u3427\u3428\u3429\u342a\u342b\u342c\u342d\u342e\u342f\u3430\u3431\u3432\u3433\u3434\u3435\u3436\u3437\u3438\u3439\u343a\u343b\u343c\u343d\u343e\u343f\u3440\u3441\u3442\u3443\u3444\u3445\u3446\u3447\u3448\u3449\u344a\u344b\u344c\u344d\u344e\u344f\u3450\u3451\u3452\u3453\u3454\u3455\u3456\u3457\u3458\u3459\u345a\u345b\u345c\u345d\u345e\u345f\u3460\u3461\u3462\u3463\u3464\u3465\u3466\u3467\u3468\u3469\u346a\u346b\u346c\u346d\u346e\u346f\u3470\u3471\u3472\u3473\u3474\u3475\u3476\u3477\u3478\u3479\u347a\u347b\u347c\u347d\u347e\u347f\u3480\u3481\u3482\u3483\u3484\u3485\u3486\u3487\u3488\u3489\u348a\u348b\u348c\u348d\u348e\u348f\u3490\u3491\u3492\u3493\u3494\u3495\u3496\u3497\u3498\u3499\u349a\u349b\u349c\u349d\u349e\u349f\u34a0\u34a1\u34a2\u34a3\u34a4\u34a5\u34a6\u34a7\u34a8\u34a9\u34aa\u34ab\u34ac\u34ad\u34ae\u34af\u34b0\u34b1\u34b2\u34b3\u34b4\u34b5\u34b6\u34b7\u34b8\u34b9\u34ba\u34bb\u34bc\u34bd\u34be\u34bf\u34c0\u34c1\u34c2\u34c3\u34c4\u34c5\u34c6\u34c7\u34c8\u34c9\u34ca\u34cb\u34cc\u34cd\u34ce\u34cf\u34d0\u34d1\u34d2\u34d3\u34d4\u34d5\u34d6\u34d7\u34d8\u34d9\u34da\u34db\u34dc\u34dd\u34de\u34df\u34e0\u34e1\u34e2\u34e3\u34e4\u34e5\u34e6\u34e7\u34e8\u34e9\u34ea\u34eb\u34ec\u34ed\u34ee\u34ef\u34f0\u34f1\u34f2\u34f3\u34f4\u34f5\u34f6\u34f7\u34f8\u34f9\u34fa\u34fb\u34fc\u34fd\u34fe\u34ff\u3500\u3501\u3502\u3503\u3504\u3505\u3506\u3507\u3508\u3509\u350a\u350b\u350c\u350d\u350e\u350f\u3510\u3511\u3512\u3513\u3514\u3515\u3516\u3517\u3518\u3519\u351a\u351b\u351c\u351d\u351e\u351f\u3520\u3521\u3522\u3523\u3524\u3525\u3526\u3527\u3528\u3529\u352a\u352b\u352c\u352d\u352e\u352f\u3530\u3531\u3532\u3533\u3534\u3535\u3536\u3537\u3538\u3539\u353a\u353b\u353c\u353d\u353e\u353f\u3540\u3541\u3542\u3543\u3544\u3545\u3546\u3547\u3548\u3549\u354a\u354b\u354c\u354d\u354e\u354f\u3550\u3551\u3552\u3553\u3554\u3555\u3556\u3557\u3558\u3559\u355a\u355b\u355c\u355d\u355e\u355f\u3560\u3561\u3562\u3563\u3564\u3565\u3566\u3567\u3568\u3569\u356a\u356b\u356c\u356d\u356e\u356f\u3570\u3571\u3572\u3573\u3574\u3575\u3576\u3577\u3578\u3579\u357a\u357b\u357c\u357d\u357e\u357f\u3580\u3581\u3582\u3583\u3584\u3585\u3586\u3587\u3588\u3589\u358a\u358b\u358c\u358d\u358e\u358f\u3590\u3591\u3592\u3593\u3594\u3595\u3596\u3597\u3598\u3599\u359a\u359b\u359c\u359d\u359e\u359f\u35a0\u35a1\u35a2\u35a3\u35a4\u35a5\u35a6\u35a7\u35a8\u35a9\u35aa\u35ab\u35ac\u35ad\u35ae\u35af\u35b0\u35b1\u35b2\u35b3\u35b4\u35b5\u35b6\u35b7\u35b8\u35b9\u35ba\u35bb\u35bc\u35bd\u35be\u35bf\u35c0\u35c1\u35c2\u35c3\u35c4\u35c5\u35c6\u35c7\u35c8\u35c9\u35ca\u35cb\u35cc\u35cd\u35ce\u35cf\u35d0\u35d1\u35d2\u35d3\u35d4\u35d5\u35d6\u35d7\u35d8\u35d9\u35da\u35db\u35dc\u35dd\u35de\u35df\u35e0\u35e1\u35e2\u35e3\u35e4\u35e5\u35e6\u35e7\u35e8\u35e9\u35ea\u35eb\u35ec\u35ed\u35ee\u35ef\u35f0\u35f1\u35f2\u35f3\u35f4\u35f5\u35f6\u35f7\u35f8\u35f9\u35fa\u35fb\u35fc\u35fd\u35fe\u35ff\u3600\u3601\u3602\u3603\u3604\u3605\u3606\u3607\u3608\u3609\u360a\u360b\u360c\u360d\u360e\u360f\u3610\u3611\u3612\u3613\u3614\u3615\u3616\u3617\u3618\u3619\u361a\u361b\u361c\u361d\u361e\u361f\u3620\u3621\u3622\u3623\u3624\u3625\u3626\u3627\u3628\u3629\u362a\u362b\u362c\u362d\u362e\u362f\u3630\u3631\u3632\u3633\u3634\u3635\u3636\u3637\u3638\u3639\u363a\u363b\u363c\u363d\u363e\u363f\u3640\u3641\u3642\u3643\u3644\u3645\u3646\u3647\u3648\u3649\u364a\u364b\u364c\u364d\u364e\u364f\u3650\u3651\u3652\u3653\u3654\u3655\u3656\u3657\u3658\u3659\u365a\u365b\u365c\u365d\u365e\u365f\u3660\u3661\u3662\u3663\u3664\u3665\u3666\u3667\u3668\u3669\u366a\u366b\u366c\u366d\u366e\u366f\u3670\u3671\u3672\u3673\u3674\u3675\u3676\u3677\u3678\u3679\u367a\u367b\u367c\u367d\u367e\u367f\u3680\u3681\u3682\u3683\u3684\u3685\u3686\u3687\u3688\u3689\u368a\u368b\u368c\u368d\u368e\u368f\u3690\u3691\u3692\u3693\u3694\u3695\u3696\u3697\u3698\u3699\u369a\u369b\u369c\u369d\u369e\u369f\u36a0\u36a1\u36a2\u36a3\u36a4\u36a5\u36a6\u36a7\u36a8\u36a9\u36aa\u36ab\u36ac\u36ad\u36ae\u36af\u36b0\u36b1\u36b2\u36b3\u36b4\u36b5\u36b6\u36b7\u36b8\u36b9\u36ba\u36bb\u36bc\u36bd\u36be\u36bf\u36c0\u36c1\u36c2\u36c3\u36c4\u36c5\u36c6\u36c7\u36c8\u36c9\u36ca\u36cb\u36cc\u36cd\u36ce\u36cf\u36d0\u36d1\u36d2\u36d3\u36d4\u36d5\u36d6\u36d7\u36d8\u36d9\u36da\u36db\u36dc\u36dd\u36de\u36df\u36e0\u36e1\u36e2\u36e3\u36e4\u36e5\u36e6\u36e7\u36e8\u36e9\u36ea\u36eb\u36ec\u36ed\u36ee\u36ef\u36f0\u36f1\u36f2\u36f3\u36f4\u36f5\u36f6\u36f7\u36f8\u36f9\u36fa\u36fb\u36fc\u36fd\u36fe\u36ff\u3700\u3701\u3702\u3703\u3704\u3705\u3706\u3707\u3708\u3709\u370a\u370b\u370c\u370d\u370e\u370f\u3710\u3711\u3712\u3713\u3714\u3715\u3716\u3717\u3718\u3719\u371a\u371b\u371c\u371d\u371e\u371f\u3720\u3721\u3722\u3723\u3724\u3725\u3726\u3727\u3728\u3729\u372a\u372b\u372c\u372d\u372e\u372f\u3730\u3731\u3732\u3733\u3734\u3735\u3736\u3737\u3738\u3739\u373a\u373b\u373c\u373d\u373e\u373f\u3740\u3741\u3742\u3743\u3744\u3745\u3746\u3747\u3748\u3749\u374a\u374b\u374c\u374d\u374e\u374f\u3750\u3751\u3752\u3753\u3754\u3755\u3756\u3757\u3758\u3759\u375a\u375b\u375c\u375d\u375e\u375f\u3760\u3761\u3762\u3763\u3764\u3765\u3766\u3767\u3768\u3769\u376a\u376b\u376c\u376d\u376e\u376f\u3770\u3771\u3772\u3773\u3774\u3775\u3776\u3777\u3778\u3779\u377a\u377b\u377c\u377d\u377e\u377f\u3780\u3781\u3782\u3783\u3784\u3785\u3786\u3787\u3788\u3789\u378a\u378b\u378c\u378d\u378e\u378f\u3790\u3791\u3792\u3793\u3794\u3795\u3796\u3797\u3798\u3799\u379a\u379b\u379c\u379d\u379e\u379f\u37a0\u37a1\u37a2\u37a3\u37a4\u37a5\u37a6\u37a7\u37a8\u37a9\u37aa\u37ab\u37ac\u37ad\u37ae\u37af\u37b0\u37b1\u37b2\u37b3\u37b4\u37b5\u37b6\u37b7\u37b8\u37b9\u37ba\u37bb\u37bc\u37bd\u37be\u37bf\u37c0\u37c1\u37c2\u37c3\u37c4\u37c5\u37c6\u37c7\u37c8\u37c9\u37ca\u37cb\u37cc\u37cd\u37ce\u37cf\u37d0\u37d1\u37d2\u37d3\u37d4\u37d5\u37d6\u37d7\u37d8\u37d9\u37da\u37db\u37dc\u37dd\u37de\u37df\u37e0\u37e1\u37e2\u37e3\u37e4\u37e5\u37e6\u37e7\u37e8\u37e9\u37ea\u37eb\u37ec\u37ed\u37ee\u37ef\u37f0\u37f1\u37f2\u37f3\u37f4\u37f5\u37f6\u37f7\u37f8\u37f9\u37fa\u37fb\u37fc\u37fd\u37fe\u37ff\u3800\u3801\u3802\u3803\u3804\u3805\u3806\u3807\u3808\u3809\u380a\u380b\u380c\u380d\u380e\u380f\u3810\u3811\u3812\u3813\u3814\u3815\u3816\u3817\u3818\u3819\u381a\u381b\u381c\u381d\u381e\u381f\u3820\u3821\u3822\u3823\u3824\u3825\u3826\u3827\u3828\u3829\u382a\u382b\u382c\u382d\u382e\u382f\u3830\u3831\u3832\u3833\u3834\u3835\u3836\u3837\u3838\u3839\u383a\u383b\u383c\u383d\u383e\u383f\u3840\u3841\u3842\u3843\u3844\u3845\u3846\u3847\u3848\u3849\u384a\u384b\u384c\u384d\u384e\u384f\u3850\u3851\u3852\u3853\u3854\u3855\u3856\u3857\u3858\u3859\u385a\u385b\u385c\u385d\u385e\u385f\u3860\u3861\u3862\u3863\u3864\u3865\u3866\u3867\u3868\u3869\u386a\u386b\u386c\u386d\u386e\u386f\u3870\u3871\u3872\u3873\u3874\u3875\u3876\u3877\u3878\u3879\u387a\u387b\u387c\u387d\u387e\u387f\u3880\u3881\u3882\u3883\u3884\u3885\u3886\u3887\u3888\u3889\u388a\u388b\u388c\u388d\u388e\u388f\u3890\u3891\u3892\u3893\u3894\u3895\u3896\u3897\u3898\u3899\u389a\u389b\u389c\u389d\u389e\u389f\u38a0\u38a1\u38a2\u38a3\u38a4\u38a5\u38a6\u38a7\u38a8\u38a9\u38aa\u38ab\u38ac\u38ad\u38ae\u38af\u38b0\u38b1\u38b2\u38b3\u38b4\u38b5\u38b6\u38b7\u38b8\u38b9\u38ba\u38bb\u38bc\u38bd\u38be\u38bf\u38c0\u38c1\u38c2\u38c3\u38c4\u38c5\u38c6\u38c7\u38c8\u38c9\u38ca\u38cb\u38cc\u38cd\u38ce\u38cf\u38d0\u38d1\u38d2\u38d3\u38d4\u38d5\u38d6\u38d7\u38d8\u38d9\u38da\u38db\u38dc\u38dd\u38de\u38df\u38e0\u38e1\u38e2\u38e3\u38e4\u38e5\u38e6\u38e7\u38e8\u38e9\u38ea\u38eb\u38ec\u38ed\u38ee\u38ef\u38f0\u38f1\u38f2\u38f3\u38f4\u38f5\u38f6\u38f7\u38f8\u38f9\u38fa\u38fb\u38fc\u38fd\u38fe\u38ff\u3900\u3901\u3902\u3903\u3904\u3905\u3906\u3907\u3908\u3909\u390a\u390b\u390c\u390d\u390e\u390f\u3910\u3911\u3912\u3913\u3914\u3915\u3916\u3917\u3918\u3919\u391a\u391b\u391c\u391d\u391e\u391f\u3920\u3921\u3922\u3923\u3924\u3925\u3926\u3927\u3928\u3929\u392a\u392b\u392c\u392d\u392e\u392f\u3930\u3931\u3932\u3933\u3934\u3935\u3936\u3937\u3938\u3939\u393a\u393b\u393c\u393d\u393e\u393f\u3940\u3941\u3942\u3943\u3944\u3945\u3946\u3947\u3948\u3949\u394a\u394b\u394c\u394d\u394e\u394f\u3950\u3951\u3952\u3953\u3954\u3955\u3956\u3957\u3958\u3959\u395a\u395b\u395c\u395d\u395e\u395f\u3960\u3961\u3962\u3963\u3964\u3965\u3966\u3967\u3968\u3969\u396a\u396b\u396c\u396d\u396e\u396f\u3970\u3971\u3972\u3973\u3974\u3975\u3976\u3977\u3978\u3979\u397a\u397b\u397c\u397d\u397e\u397f\u3980\u3981\u3982\u3983\u3984\u3985\u3986\u3987\u3988\u3989\u398a\u398b\u398c\u398d\u398e\u398f\u3990\u3991\u3992\u3993\u3994\u3995\u3996\u3997\u3998\u3999\u399a\u399b\u399c\u399d\u399e\u399f\u39a0\u39a1\u39a2\u39a3\u39a4\u39a5\u39a6\u39a7\u39a8\u39a9\u39aa\u39ab\u39ac\u39ad\u39ae\u39af\u39b0\u39b1\u39b2\u39b3\u39b4\u39b5\u39b6\u39b7\u39b8\u39b9\u39ba\u39bb\u39bc\u39bd\u39be\u39bf\u39c0\u39c1\u39c2\u39c3\u39c4\u39c5\u39c6\u39c7\u39c8\u39c9\u39ca\u39cb\u39cc\u39cd\u39ce\u39cf\u39d0\u39d1\u39d2\u39d3\u39d4\u39d5\u39d6\u39d7\u39d8\u39d9\u39da\u39db\u39dc\u39dd\u39de\u39df\u39e0\u39e1\u39e2\u39e3\u39e4\u39e5\u39e6\u39e7\u39e8\u39e9\u39ea\u39eb\u39ec\u39ed\u39ee\u39ef\u39f0\u39f1\u39f2\u39f3\u39f4\u39f5\u39f6\u39f7\u39f8\u39f9\u39fa\u39fb\u39fc\u39fd\u39fe\u39ff\u3a00\u3a01\u3a02\u3a03\u3a04\u3a05\u3a06\u3a07\u3a08\u3a09\u3a0a\u3a0b\u3a0c\u3a0d\u3a0e\u3a0f\u3a10\u3a11\u3a12\u3a13\u3a14\u3a15\u3a16\u3a17\u3a18\u3a19\u3a1a\u3a1b\u3a1c\u3a1d\u3a1e\u3a1f\u3a20\u3a21\u3a22\u3a23\u3a24\u3a25\u3a26\u3a27\u3a28\u3a29\u3a2a\u3a2b\u3a2c\u3a2d\u3a2e\u3a2f\u3a30\u3a31\u3a32\u3a33\u3a34\u3a35\u3a36\u3a37\u3a38\u3a39\u3a3a\u3a3b\u3a3c\u3a3d\u3a3e\u3a3f\u3a40\u3a41\u3a42\u3a43\u3a44\u3a45\u3a46\u3a47\u3a48\u3a49\u3a4a\u3a4b\u3a4c\u3a4d\u3a4e\u3a4f\u3a50\u3a51\u3a52\u3a53\u3a54\u3a55\u3a56\u3a57\u3a58\u3a59\u3a5a\u3a5b\u3a5c\u3a5d\u3a5e\u3a5f\u3a60\u3a61\u3a62\u3a63\u3a64\u3a65\u3a66\u3a67\u3a68\u3a69\u3a6a\u3a6b\u3a6c\u3a6d\u3a6e\u3a6f\u3a70\u3a71\u3a72\u3a73\u3a74\u3a75\u3a76\u3a77\u3a78\u3a79\u3a7a\u3a7b\u3a7c\u3a7d\u3a7e\u3a7f\u3a80\u3a81\u3a82\u3a83\u3a84\u3a85\u3a86\u3a87\u3a88\u3a89\u3a8a\u3a8b\u3a8c\u3a8d\u3a8e\u3a8f\u3a90\u3a91\u3a92\u3a93\u3a94\u3a95\u3a96\u3a97\u3a98\u3a99\u3a9a\u3a9b\u3a9c\u3a9d\u3a9e\u3a9f\u3aa0\u3aa1\u3aa2\u3aa3\u3aa4\u3aa5\u3aa6\u3aa7\u3aa8\u3aa9\u3aaa\u3aab\u3aac\u3aad\u3aae\u3aaf\u3ab0\u3ab1\u3ab2\u3ab3\u3ab4\u3ab5\u3ab6\u3ab7\u3ab8\u3ab9\u3aba\u3abb\u3abc\u3abd\u3abe\u3abf\u3ac0\u3ac1\u3ac2\u3ac3\u3ac4\u3ac5\u3ac6\u3ac7\u3ac8\u3ac9\u3aca\u3acb\u3acc\u3acd\u3ace\u3acf\u3ad0\u3ad1\u3ad2\u3ad3\u3ad4\u3ad5\u3ad6\u3ad7\u3ad8\u3ad9\u3ada\u3adb\u3adc\u3add\u3ade\u3adf\u3ae0\u3ae1\u3ae2\u3ae3\u3ae4\u3ae5\u3ae6\u3ae7\u3ae8\u3ae9\u3aea\u3aeb\u3aec\u3aed\u3aee\u3aef\u3af0\u3af1\u3af2\u3af3\u3af4\u3af5\u3af6\u3af7\u3af8\u3af9\u3afa\u3afb\u3afc\u3afd\u3afe\u3aff\u3b00\u3b01\u3b02\u3b03\u3b04\u3b05\u3b06\u3b07\u3b08\u3b09\u3b0a\u3b0b\u3b0c\u3b0d\u3b0e\u3b0f\u3b10\u3b11\u3b12\u3b13\u3b14\u3b15\u3b16\u3b17\u3b18\u3b19\u3b1a\u3b1b\u3b1c\u3b1d\u3b1e\u3b1f\u3b20\u3b21\u3b22\u3b23\u3b24\u3b25\u3b26\u3b27\u3b28\u3b29\u3b2a\u3b2b\u3b2c\u3b2d\u3b2e\u3b2f\u3b30\u3b31\u3b32\u3b33\u3b34\u3b35\u3b36\u3b37\u3b38\u3b39\u3b3a\u3b3b\u3b3c\u3b3d\u3b3e\u3b3f\u3b40\u3b41\u3b42\u3b43\u3b44\u3b45\u3b46\u3b47\u3b48\u3b49\u3b4a\u3b4b\u3b4c\u3b4d\u3b4e\u3b4f\u3b50\u3b51\u3b52\u3b53\u3b54\u3b55\u3b56\u3b57\u3b58\u3b59\u3b5a\u3b5b\u3b5c\u3b5d\u3b5e\u3b5f\u3b60\u3b61\u3b62\u3b63\u3b64\u3b65\u3b66\u3b67\u3b68\u3b69\u3b6a\u3b6b\u3b6c\u3b6d\u3b6e\u3b6f\u3b70\u3b71\u3b72\u3b73\u3b74\u3b75\u3b76\u3b77\u3b78\u3b79\u3b7a\u3b7b\u3b7c\u3b7d\u3b7e\u3b7f\u3b80\u3b81\u3b82\u3b83\u3b84\u3b85\u3b86\u3b87\u3b88\u3b89\u3b8a\u3b8b\u3b8c\u3b8d\u3b8e\u3b8f\u3b90\u3b91\u3b92\u3b93\u3b94\u3b95\u3b96\u3b97\u3b98\u3b99\u3b9a\u3b9b\u3b9c\u3b9d\u3b9e\u3b9f\u3ba0\u3ba1\u3ba2\u3ba3\u3ba4\u3ba5\u3ba6\u3ba7\u3ba8\u3ba9\u3baa\u3bab\u3bac\u3bad\u3bae\u3baf\u3bb0\u3bb1\u3bb2\u3bb3\u3bb4\u3bb5\u3bb6\u3bb7\u3bb8\u3bb9\u3bba\u3bbb\u3bbc\u3bbd\u3bbe\u3bbf\u3bc0\u3bc1\u3bc2\u3bc3\u3bc4\u3bc5\u3bc6\u3bc7\u3bc8\u3bc9\u3bca\u3bcb\u3bcc\u3bcd\u3bce\u3bcf\u3bd0\u3bd1\u3bd2\u3bd3\u3bd4\u3bd5\u3bd6\u3bd7\u3bd8\u3bd9\u3bda\u3bdb\u3bdc\u3bdd\u3bde\u3bdf\u3be0\u3be1\u3be2\u3be3\u3be4\u3be5\u3be6\u3be7\u3be8\u3be9\u3bea\u3beb\u3bec\u3bed\u3bee\u3bef\u3bf0\u3bf1\u3bf2\u3bf3\u3bf4\u3bf5\u3bf6\u3bf7\u3bf8\u3bf9\u3bfa\u3bfb\u3bfc\u3bfd\u3bfe\u3bff\u3c00\u3c01\u3c02\u3c03\u3c04\u3c05\u3c06\u3c07\u3c08\u3c09\u3c0a\u3c0b\u3c0c\u3c0d\u3c0e\u3c0f\u3c10\u3c11\u3c12\u3c13\u3c14\u3c15\u3c16\u3c17\u3c18\u3c19\u3c1a\u3c1b\u3c1c\u3c1d\u3c1e\u3c1f\u3c20\u3c21\u3c22\u3c23\u3c24\u3c25\u3c26\u3c27\u3c28\u3c29\u3c2a\u3c2b\u3c2c\u3c2d\u3c2e\u3c2f\u3c30\u3c31\u3c32\u3c33\u3c34\u3c35\u3c36\u3c37\u3c38\u3c39\u3c3a\u3c3b\u3c3c\u3c3d\u3c3e\u3c3f\u3c40\u3c41\u3c42\u3c43\u3c44\u3c45\u3c46\u3c47\u3c48\u3c49\u3c4a\u3c4b\u3c4c\u3c4d\u3c4e\u3c4f\u3c50\u3c51\u3c52\u3c53\u3c54\u3c55\u3c56\u3c57\u3c58\u3c59\u3c5a\u3c5b\u3c5c\u3c5d\u3c5e\u3c5f\u3c60\u3c61\u3c62\u3c63\u3c64\u3c65\u3c66\u3c67\u3c68\u3c69\u3c6a\u3c6b\u3c6c\u3c6d\u3c6e\u3c6f\u3c70\u3c71\u3c72\u3c73\u3c74\u3c75\u3c76\u3c77\u3c78\u3c79\u3c7a\u3c7b\u3c7c\u3c7d\u3c7e\u3c7f\u3c80\u3c81\u3c82\u3c83\u3c84\u3c85\u3c86\u3c87\u3c88\u3c89\u3c8a\u3c8b\u3c8c\u3c8d\u3c8e\u3c8f\u3c90\u3c91\u3c92\u3c93\u3c94\u3c95\u3c96\u3c97\u3c98\u3c99\u3c9a\u3c9b\u3c9c\u3c9d\u3c9e\u3c9f\u3ca0\u3ca1\u3ca2\u3ca3\u3ca4\u3ca5\u3ca6\u3ca7\u3ca8\u3ca9\u3caa\u3cab\u3cac\u3cad\u3cae\u3caf\u3cb0\u3cb1\u3cb2\u3cb3\u3cb4\u3cb5\u3cb6\u3cb7\u3cb8\u3cb9\u3cba\u3cbb\u3cbc\u3cbd\u3cbe\u3cbf\u3cc0\u3cc1\u3cc2\u3cc3\u3cc4\u3cc5\u3cc6\u3cc7\u3cc8\u3cc9\u3cca\u3ccb\u3ccc\u3ccd\u3cce\u3ccf\u3cd0\u3cd1\u3cd2\u3cd3\u3cd4\u3cd5\u3cd6\u3cd7\u3cd8\u3cd9\u3cda\u3cdb\u3cdc\u3cdd\u3cde\u3cdf\u3ce0\u3ce1\u3ce2\u3ce3\u3ce4\u3ce5\u3ce6\u3ce7\u3ce8\u3ce9\u3cea\u3ceb\u3cec\u3ced\u3cee\u3cef\u3cf0\u3cf1\u3cf2\u3cf3\u3cf4\u3cf5\u3cf6\u3cf7\u3cf8\u3cf9\u3cfa\u3cfb\u3cfc\u3cfd\u3cfe\u3cff\u3d00\u3d01\u3d02\u3d03\u3d04\u3d05\u3d06\u3d07\u3d08\u3d09\u3d0a\u3d0b\u3d0c\u3d0d\u3d0e\u3d0f\u3d10\u3d11\u3d12\u3d13\u3d14\u3d15\u3d16\u3d17\u3d18\u3d19\u3d1a\u3d1b\u3d1c\u3d1d\u3d1e\u3d1f\u3d20\u3d21\u3d22\u3d23\u3d24\u3d25\u3d26\u3d27\u3d28\u3d29\u3d2a\u3d2b\u3d2c\u3d2d\u3d2e\u3d2f\u3d30\u3d31\u3d32\u3d33\u3d34\u3d35\u3d36\u3d37\u3d38\u3d39\u3d3a\u3d3b\u3d3c\u3d3d\u3d3e\u3d3f\u3d40\u3d41\u3d42\u3d43\u3d44\u3d45\u3d46\u3d47\u3d48\u3d49\u3d4a\u3d4b\u3d4c\u3d4d\u3d4e\u3d4f\u3d50\u3d51\u3d52\u3d53\u3d54\u3d55\u3d56\u3d57\u3d58\u3d59\u3d5a\u3d5b\u3d5c\u3d5d\u3d5e\u3d5f\u3d60\u3d61\u3d62\u3d63\u3d64\u3d65\u3d66\u3d67\u3d68\u3d69\u3d6a\u3d6b\u3d6c\u3d6d\u3d6e\u3d6f\u3d70\u3d71\u3d72\u3d73\u3d74\u3d75\u3d76\u3d77\u3d78\u3d79\u3d7a\u3d7b\u3d7c\u3d7d\u3d7e\u3d7f\u3d80\u3d81\u3d82\u3d83\u3d84\u3d85\u3d86\u3d87\u3d88\u3d89\u3d8a\u3d8b\u3d8c\u3d8d\u3d8e\u3d8f\u3d90\u3d91\u3d92\u3d93\u3d94\u3d95\u3d96\u3d97\u3d98\u3d99\u3d9a\u3d9b\u3d9c\u3d9d\u3d9e\u3d9f\u3da0\u3da1\u3da2\u3da3\u3da4\u3da5\u3da6\u3da7\u3da8\u3da9\u3daa\u3dab\u3dac\u3dad\u3dae\u3daf\u3db0\u3db1\u3db2\u3db3\u3db4\u3db5\u3db6\u3db7\u3db8\u3db9\u3dba\u3dbb\u3dbc\u3dbd\u3dbe\u3dbf\u3dc0\u3dc1\u3dc2\u3dc3\u3dc4\u3dc5\u3dc6\u3dc7\u3dc8\u3dc9\u3dca\u3dcb\u3dcc\u3dcd\u3dce\u3dcf\u3dd0\u3dd1\u3dd2\u3dd3\u3dd4\u3dd5\u3dd6\u3dd7\u3dd8\u3dd9\u3dda\u3ddb\u3ddc\u3ddd\u3dde\u3ddf\u3de0\u3de1\u3de2\u3de3\u3de4\u3de5\u3de6\u3de7\u3de8\u3de9\u3dea\u3deb\u3dec\u3ded\u3dee\u3def\u3df0\u3df1\u3df2\u3df3\u3df4\u3df5\u3df6\u3df7\u3df8\u3df9\u3dfa\u3dfb\u3dfc\u3dfd\u3dfe\u3dff\u3e00\u3e01\u3e02\u3e03\u3e04\u3e05\u3e06\u3e07\u3e08\u3e09\u3e0a\u3e0b\u3e0c\u3e0d\u3e0e\u3e0f\u3e10\u3e11\u3e12\u3e13\u3e14\u3e15\u3e16\u3e17\u3e18\u3e19\u3e1a\u3e1b\u3e1c\u3e1d\u3e1e\u3e1f\u3e20\u3e21\u3e22\u3e23\u3e24\u3e25\u3e26\u3e27\u3e28\u3e29\u3e2a\u3e2b\u3e2c\u3e2d\u3e2e\u3e2f\u3e30\u3e31\u3e32\u3e33\u3e34\u3e35\u3e36\u3e37\u3e38\u3e39\u3e3a\u3e3b\u3e3c\u3e3d\u3e3e\u3e3f\u3e40\u3e41\u3e42\u3e43\u3e44\u3e45\u3e46\u3e47\u3e48\u3e49\u3e4a\u3e4b\u3e4c\u3e4d\u3e4e\u3e4f\u3e50\u3e51\u3e52\u3e53\u3e54\u3e55\u3e56\u3e57\u3e58\u3e59\u3e5a\u3e5b\u3e5c\u3e5d\u3e5e\u3e5f\u3e60\u3e61\u3e62\u3e63\u3e64\u3e65\u3e66\u3e67\u3e68\u3e69\u3e6a\u3e6b\u3e6c\u3e6d\u3e6e\u3e6f\u3e70\u3e71\u3e72\u3e73\u3e74\u3e75\u3e76\u3e77\u3e78\u3e79\u3e7a\u3e7b\u3e7c\u3e7d\u3e7e\u3e7f\u3e80\u3e81\u3e82\u3e83\u3e84\u3e85\u3e86\u3e87\u3e88\u3e89\u3e8a\u3e8b\u3e8c\u3e8d\u3e8e\u3e8f\u3e90\u3e91\u3e92\u3e93\u3e94\u3e95\u3e96\u3e97\u3e98\u3e99\u3e9a\u3e9b\u3e9c\u3e9d\u3e9e\u3e9f\u3ea0\u3ea1\u3ea2\u3ea3\u3ea4\u3ea5\u3ea6\u3ea7\u3ea8\u3ea9\u3eaa\u3eab\u3eac\u3ead\u3eae\u3eaf\u3eb0\u3eb1\u3eb2\u3eb3\u3eb4\u3eb5\u3eb6\u3eb7\u3eb8\u3eb9\u3eba\u3ebb\u3ebc\u3ebd\u3ebe\u3ebf\u3ec0\u3ec1\u3ec2\u3ec3\u3ec4\u3ec5\u3ec6\u3ec7\u3ec8\u3ec9\u3eca\u3ecb\u3ecc\u3ecd\u3ece\u3ecf\u3ed0\u3ed1\u3ed2\u3ed3\u3ed4\u3ed5\u3ed6\u3ed7\u3ed8\u3ed9\u3eda\u3edb\u3edc\u3edd\u3ede\u3edf\u3ee0\u3ee1\u3ee2\u3ee3\u3ee4\u3ee5\u3ee6\u3ee7\u3ee8\u3ee9\u3eea\u3eeb\u3eec\u3eed\u3eee\u3eef\u3ef0\u3ef1\u3ef2\u3ef3\u3ef4\u3ef5\u3ef6\u3ef7\u3ef8\u3ef9\u3efa\u3efb\u3efc\u3efd\u3efe\u3eff\u3f00\u3f01\u3f02\u3f03\u3f04\u3f05\u3f06\u3f07\u3f08\u3f09\u3f0a\u3f0b\u3f0c\u3f0d\u3f0e\u3f0f\u3f10\u3f11\u3f12\u3f13\u3f14\u3f15\u3f16\u3f17\u3f18\u3f19\u3f1a\u3f1b\u3f1c\u3f1d\u3f1e\u3f1f\u3f20\u3f21\u3f22\u3f23\u3f24\u3f25\u3f26\u3f27\u3f28\u3f29\u3f2a\u3f2b\u3f2c\u3f2d\u3f2e\u3f2f\u3f30\u3f31\u3f32\u3f33\u3f34\u3f35\u3f36\u3f37\u3f38\u3f39\u3f3a\u3f3b\u3f3c\u3f3d\u3f3e\u3f3f\u3f40\u3f41\u3f42\u3f43\u3f44\u3f45\u3f46\u3f47\u3f48\u3f49\u3f4a\u3f4b\u3f4c\u3f4d\u3f4e\u3f4f\u3f50\u3f51\u3f52\u3f53\u3f54\u3f55\u3f56\u3f57\u3f58\u3f59\u3f5a\u3f5b\u3f5c\u3f5d\u3f5e\u3f5f\u3f60\u3f61\u3f62\u3f63\u3f64\u3f65\u3f66\u3f67\u3f68\u3f69\u3f6a\u3f6b\u3f6c\u3f6d\u3f6e\u3f6f\u3f70\u3f71\u3f72\u3f73\u3f74\u3f75\u3f76\u3f77\u3f78\u3f79\u3f7a\u3f7b\u3f7c\u3f7d\u3f7e\u3f7f\u3f80\u3f81\u3f82\u3f83\u3f84\u3f85\u3f86\u3f87\u3f88\u3f89\u3f8a\u3f8b\u3f8c\u3f8d\u3f8e\u3f8f\u3f90\u3f91\u3f92\u3f93\u3f94\u3f95\u3f96\u3f97\u3f98\u3f99\u3f9a\u3f9b\u3f9c\u3f9d\u3f9e\u3f9f\u3fa0\u3fa1\u3fa2\u3fa3\u3fa4\u3fa5\u3fa6\u3fa7\u3fa8\u3fa9\u3faa\u3fab\u3fac\u3fad\u3fae\u3faf\u3fb0\u3fb1\u3fb2\u3fb3\u3fb4\u3fb5\u3fb6\u3fb7\u3fb8\u3fb9\u3fba\u3fbb\u3fbc\u3fbd\u3fbe\u3fbf\u3fc0\u3fc1\u3fc2\u3fc3\u3fc4\u3fc5\u3fc6\u3fc7\u3fc8\u3fc9\u3fca\u3fcb\u3fcc\u3fcd\u3fce\u3fcf\u3fd0\u3fd1\u3fd2\u3fd3\u3fd4\u3fd5\u3fd6\u3fd7\u3fd8\u3fd9\u3fda\u3fdb\u3fdc\u3fdd\u3fde\u3fdf\u3fe0\u3fe1\u3fe2\u3fe3\u3fe4\u3fe5\u3fe6\u3fe7\u3fe8\u3fe9\u3fea\u3feb\u3fec\u3fed\u3fee\u3fef\u3ff0\u3ff1\u3ff2\u3ff3\u3ff4\u3ff5\u3ff6\u3ff7\u3ff8\u3ff9\u3ffa\u3ffb\u3ffc\u3ffd\u3ffe\u3fff\u4000\u4001\u4002\u4003\u4004\u4005\u4006\u4007\u4008\u4009\u400a\u400b\u400c\u400d\u400e\u400f\u4010\u4011\u4012\u4013\u4014\u4015\u4016\u4017\u4018\u4019\u401a\u401b\u401c\u401d\u401e\u401f\u4020\u4021\u4022\u4023\u4024\u4025\u4026\u4027\u4028\u4029\u402a\u402b\u402c\u402d\u402e\u402f\u4030\u4031\u4032\u4033\u4034\u4035\u4036\u4037\u4038\u4039\u403a\u403b\u403c\u403d\u403e\u403f\u4040\u4041\u4042\u4043\u4044\u4045\u4046\u4047\u4048\u4049\u404a\u404b\u404c\u404d\u404e\u404f\u4050\u4051\u4052\u4053\u4054\u4055\u4056\u4057\u4058\u4059\u405a\u405b\u405c\u405d\u405e\u405f\u4060\u4061\u4062\u4063\u4064\u4065\u4066\u4067\u4068\u4069\u406a\u406b\u406c\u406d\u406e\u406f\u4070\u4071\u4072\u4073\u4074\u4075\u4076\u4077\u4078\u4079\u407a\u407b\u407c\u407d\u407e\u407f\u4080\u4081\u4082\u4083\u4084\u4085\u4086\u4087\u4088\u4089\u408a\u408b\u408c\u408d\u408e\u408f\u4090\u4091\u4092\u4093\u4094\u4095\u4096\u4097\u4098\u4099\u409a\u409b\u409c\u409d\u409e\u409f\u40a0\u40a1\u40a2\u40a3\u40a4\u40a5\u40a6\u40a7\u40a8\u40a9\u40aa\u40ab\u40ac\u40ad\u40ae\u40af\u40b0\u40b1\u40b2\u40b3\u40b4\u40b5\u40b6\u40b7\u40b8\u40b9\u40ba\u40bb\u40bc\u40bd\u40be\u40bf\u40c0\u40c1\u40c2\u40c3\u40c4\u40c5\u40c6\u40c7\u40c8\u40c9\u40ca\u40cb\u40cc\u40cd\u40ce\u40cf\u40d0\u40d1\u40d2\u40d3\u40d4\u40d5\u40d6\u40d7\u40d8\u40d9\u40da\u40db\u40dc\u40dd\u40de\u40df\u40e0\u40e1\u40e2\u40e3\u40e4\u40e5\u40e6\u40e7\u40e8\u40e9\u40ea\u40eb\u40ec\u40ed\u40ee\u40ef\u40f0\u40f1\u40f2\u40f3\u40f4\u40f5\u40f6\u40f7\u40f8\u40f9\u40fa\u40fb\u40fc\u40fd\u40fe\u40ff\u4100\u4101\u4102\u4103\u4104\u4105\u4106\u4107\u4108\u4109\u410a\u410b\u410c\u410d\u410e\u410f\u4110\u4111\u4112\u4113\u4114\u4115\u4116\u4117\u4118\u4119\u411a\u411b\u411c\u411d\u411e\u411f\u4120\u4121\u4122\u4123\u4124\u4125\u4126\u4127\u4128\u4129\u412a\u412b\u412c\u412d\u412e\u412f\u4130\u4131\u4132\u4133\u4134\u4135\u4136\u4137\u4138\u4139\u413a\u413b\u413c\u413d\u413e\u413f\u4140\u4141\u4142\u4143\u4144\u4145\u4146\u4147\u4148\u4149\u414a\u414b\u414c\u414d\u414e\u414f\u4150\u4151\u4152\u4153\u4154\u4155\u4156\u4157\u4158\u4159\u415a\u415b\u415c\u415d\u415e\u415f\u4160\u4161\u4162\u4163\u4164\u4165\u4166\u4167\u4168\u4169\u416a\u416b\u416c\u416d\u416e\u416f\u4170\u4171\u4172\u4173\u4174\u4175\u4176\u4177\u4178\u4179\u417a\u417b\u417c\u417d\u417e\u417f\u4180\u4181\u4182\u4183\u4184\u4185\u4186\u4187\u4188\u4189\u418a\u418b\u418c\u418d\u418e\u418f\u4190\u4191\u4192\u4193\u4194\u4195\u4196\u4197\u4198\u4199\u419a\u419b\u419c\u419d\u419e\u419f\u41a0\u41a1\u41a2\u41a3\u41a4\u41a5\u41a6\u41a7\u41a8\u41a9\u41aa\u41ab\u41ac\u41ad\u41ae\u41af\u41b0\u41b1\u41b2\u41b3\u41b4\u41b5\u41b6\u41b7\u41b8\u41b9\u41ba\u41bb\u41bc\u41bd\u41be\u41bf\u41c0\u41c1\u41c2\u41c3\u41c4\u41c5\u41c6\u41c7\u41c8\u41c9\u41ca\u41cb\u41cc\u41cd\u41ce\u41cf\u41d0\u41d1\u41d2\u41d3\u41d4\u41d5\u41d6\u41d7\u41d8\u41d9\u41da\u41db\u41dc\u41dd\u41de\u41df\u41e0\u41e1\u41e2\u41e3\u41e4\u41e5\u41e6\u41e7\u41e8\u41e9\u41ea\u41eb\u41ec\u41ed\u41ee\u41ef\u41f0\u41f1\u41f2\u41f3\u41f4\u41f5\u41f6\u41f7\u41f8\u41f9\u41fa\u41fb\u41fc\u41fd\u41fe\u41ff\u4200\u4201\u4202\u4203\u4204\u4205\u4206\u4207\u4208\u4209\u420a\u420b\u420c\u420d\u420e\u420f\u4210\u4211\u4212\u4213\u4214\u4215\u4216\u4217\u4218\u4219\u421a\u421b\u421c\u421d\u421e\u421f\u4220\u4221\u4222\u4223\u4224\u4225\u4226\u4227\u4228\u4229\u422a\u422b\u422c\u422d\u422e\u422f\u4230\u4231\u4232\u4233\u4234\u4235\u4236\u4237\u4238\u4239\u423a\u423b\u423c\u423d\u423e\u423f\u4240\u4241\u4242\u4243\u4244\u4245\u4246\u4247\u4248\u4249\u424a\u424b\u424c\u424d\u424e\u424f\u4250\u4251\u4252\u4253\u4254\u4255\u4256\u4257\u4258\u4259\u425a\u425b\u425c\u425d\u425e\u425f\u4260\u4261\u4262\u4263\u4264\u4265\u4266\u4267\u4268\u4269\u426a\u426b\u426c\u426d\u426e\u426f\u4270\u4271\u4272\u4273\u4274\u4275\u4276\u4277\u4278\u4279\u427a\u427b\u427c\u427d\u427e\u427f\u4280\u4281\u4282\u4283\u4284\u4285\u4286\u4287\u4288\u4289\u428a\u428b\u428c\u428d\u428e\u428f\u4290\u4291\u4292\u4293\u4294\u4295\u4296\u4297\u4298\u4299\u429a\u429b\u429c\u429d\u429e\u429f\u42a0\u42a1\u42a2\u42a3\u42a4\u42a5\u42a6\u42a7\u42a8\u42a9\u42aa\u42ab\u42ac\u42ad\u42ae\u42af\u42b0\u42b1\u42b2\u42b3\u42b4\u42b5\u42b6\u42b7\u42b8\u42b9\u42ba\u42bb\u42bc\u42bd\u42be\u42bf\u42c0\u42c1\u42c2\u42c3\u42c4\u42c5\u42c6\u42c7\u42c8\u42c9\u42ca\u42cb\u42cc\u42cd\u42ce\u42cf\u42d0\u42d1\u42d2\u42d3\u42d4\u42d5\u42d6\u42d7\u42d8\u42d9\u42da\u42db\u42dc\u42dd\u42de\u42df\u42e0\u42e1\u42e2\u42e3\u42e4\u42e5\u42e6\u42e7\u42e8\u42e9\u42ea\u42eb\u42ec\u42ed\u42ee\u42ef\u42f0\u42f1\u42f2\u42f3\u42f4\u42f5\u42f6\u42f7\u42f8\u42f9\u42fa\u42fb\u42fc\u42fd\u42fe\u42ff\u4300\u4301\u4302\u4303\u4304\u4305\u4306\u4307\u4308\u4309\u430a\u430b\u430c\u430d\u430e\u430f\u4310\u4311\u4312\u4313\u4314\u4315\u4316\u4317\u4318\u4319\u431a\u431b\u431c\u431d\u431e\u431f\u4320\u4321\u4322\u4323\u4324\u4325\u4326\u4327\u4328\u4329\u432a\u432b\u432c\u432d\u432e\u432f\u4330\u4331\u4332\u4333\u4334\u4335\u4336\u4337\u4338\u4339\u433a\u433b\u433c\u433d\u433e\u433f\u4340\u4341\u4342\u4343\u4344\u4345\u4346\u4347\u4348\u4349\u434a\u434b\u434c\u434d\u434e\u434f\u4350\u4351\u4352\u4353\u4354\u4355\u4356\u4357\u4358\u4359\u435a\u435b\u435c\u435d\u435e\u435f\u4360\u4361\u4362\u4363\u4364\u4365\u4366\u4367\u4368\u4369\u436a\u436b\u436c\u436d\u436e\u436f\u4370\u4371\u4372\u4373\u4374\u4375\u4376\u4377\u4378\u4379\u437a\u437b\u437c\u437d\u437e\u437f\u4380\u4381\u4382\u4383\u4384\u4385\u4386\u4387\u4388\u4389\u438a\u438b\u438c\u438d\u438e\u438f\u4390\u4391\u4392\u4393\u4394\u4395\u4396\u4397\u4398\u4399\u439a\u439b\u439c\u439d\u439e\u439f\u43a0\u43a1\u43a2\u43a3\u43a4\u43a5\u43a6\u43a7\u43a8\u43a9\u43aa\u43ab\u43ac\u43ad\u43ae\u43af\u43b0\u43b1\u43b2\u43b3\u43b4\u43b5\u43b6\u43b7\u43b8\u43b9\u43ba\u43bb\u43bc\u43bd\u43be\u43bf\u43c0\u43c1\u43c2\u43c3\u43c4\u43c5\u43c6\u43c7\u43c8\u43c9\u43ca\u43cb\u43cc\u43cd\u43ce\u43cf\u43d0\u43d1\u43d2\u43d3\u43d4\u43d5\u43d6\u43d7\u43d8\u43d9\u43da\u43db\u43dc\u43dd\u43de\u43df\u43e0\u43e1\u43e2\u43e3\u43e4\u43e5\u43e6\u43e7\u43e8\u43e9\u43ea\u43eb\u43ec\u43ed\u43ee\u43ef\u43f0\u43f1\u43f2\u43f3\u43f4\u43f5\u43f6\u43f7\u43f8\u43f9\u43fa\u43fb\u43fc\u43fd\u43fe\u43ff\u4400\u4401\u4402\u4403\u4404\u4405\u4406\u4407\u4408\u4409\u440a\u440b\u440c\u440d\u440e\u440f\u4410\u4411\u4412\u4413\u4414\u4415\u4416\u4417\u4418\u4419\u441a\u441b\u441c\u441d\u441e\u441f\u4420\u4421\u4422\u4423\u4424\u4425\u4426\u4427\u4428\u4429\u442a\u442b\u442c\u442d\u442e\u442f\u4430\u4431\u4432\u4433\u4434\u4435\u4436\u4437\u4438\u4439\u443a\u443b\u443c\u443d\u443e\u443f\u4440\u4441\u4442\u4443\u4444\u4445\u4446\u4447\u4448\u4449\u444a\u444b\u444c\u444d\u444e\u444f\u4450\u4451\u4452\u4453\u4454\u4455\u4456\u4457\u4458\u4459\u445a\u445b\u445c\u445d\u445e\u445f\u4460\u4461\u4462\u4463\u4464\u4465\u4466\u4467\u4468\u4469\u446a\u446b\u446c\u446d\u446e\u446f\u4470\u4471\u4472\u4473\u4474\u4475\u4476\u4477\u4478\u4479\u447a\u447b\u447c\u447d\u447e\u447f\u4480\u4481\u4482\u4483\u4484\u4485\u4486\u4487\u4488\u4489\u448a\u448b\u448c\u448d\u448e\u448f\u4490\u4491\u4492\u4493\u4494\u4495\u4496\u4497\u4498\u4499\u449a\u449b\u449c\u449d\u449e\u449f\u44a0\u44a1\u44a2\u44a3\u44a4\u44a5\u44a6\u44a7\u44a8\u44a9\u44aa\u44ab\u44ac\u44ad\u44ae\u44af\u44b0\u44b1\u44b2\u44b3\u44b4\u44b5\u44b6\u44b7\u44b8\u44b9\u44ba\u44bb\u44bc\u44bd\u44be\u44bf\u44c0\u44c1\u44c2\u44c3\u44c4\u44c5\u44c6\u44c7\u44c8\u44c9\u44ca\u44cb\u44cc\u44cd\u44ce\u44cf\u44d0\u44d1\u44d2\u44d3\u44d4\u44d5\u44d6\u44d7\u44d8\u44d9\u44da\u44db\u44dc\u44dd\u44de\u44df\u44e0\u44e1\u44e2\u44e3\u44e4\u44e5\u44e6\u44e7\u44e8\u44e9\u44ea\u44eb\u44ec\u44ed\u44ee\u44ef\u44f0\u44f1\u44f2\u44f3\u44f4\u44f5\u44f6\u44f7\u44f8\u44f9\u44fa\u44fb\u44fc\u44fd\u44fe\u44ff\u4500\u4501\u4502\u4503\u4504\u4505\u4506\u4507\u4508\u4509\u450a\u450b\u450c\u450d\u450e\u450f\u4510\u4511\u4512\u4513\u4514\u4515\u4516\u4517\u4518\u4519\u451a\u451b\u451c\u451d\u451e\u451f\u4520\u4521\u4522\u4523\u4524\u4525\u4526\u4527\u4528\u4529\u452a\u452b\u452c\u452d\u452e\u452f\u4530\u4531\u4532\u4533\u4534\u4535\u4536\u4537\u4538\u4539\u453a\u453b\u453c\u453d\u453e\u453f\u4540\u4541\u4542\u4543\u4544\u4545\u4546\u4547\u4548\u4549\u454a\u454b\u454c\u454d\u454e\u454f\u4550\u4551\u4552\u4553\u4554\u4555\u4556\u4557\u4558\u4559\u455a\u455b\u455c\u455d\u455e\u455f\u4560\u4561\u4562\u4563\u4564\u4565\u4566\u4567\u4568\u4569\u456a\u456b\u456c\u456d\u456e\u456f\u4570\u4571\u4572\u4573\u4574\u4575\u4576\u4577\u4578\u4579\u457a\u457b\u457c\u457d\u457e\u457f\u4580\u4581\u4582\u4583\u4584\u4585\u4586\u4587\u4588\u4589\u458a\u458b\u458c\u458d\u458e\u458f\u4590\u4591\u4592\u4593\u4594\u4595\u4596\u4597\u4598\u4599\u459a\u459b\u459c\u459d\u459e\u459f\u45a0\u45a1\u45a2\u45a3\u45a4\u45a5\u45a6\u45a7\u45a8\u45a9\u45aa\u45ab\u45ac\u45ad\u45ae\u45af\u45b0\u45b1\u45b2\u45b3\u45b4\u45b5\u45b6\u45b7\u45b8\u45b9\u45ba\u45bb\u45bc\u45bd\u45be\u45bf\u45c0\u45c1\u45c2\u45c3\u45c4\u45c5\u45c6\u45c7\u45c8\u45c9\u45ca\u45cb\u45cc\u45cd\u45ce\u45cf\u45d0\u45d1\u45d2\u45d3\u45d4\u45d5\u45d6\u45d7\u45d8\u45d9\u45da\u45db\u45dc\u45dd\u45de\u45df\u45e0\u45e1\u45e2\u45e3\u45e4\u45e5\u45e6\u45e7\u45e8\u45e9\u45ea\u45eb\u45ec\u45ed\u45ee\u45ef\u45f0\u45f1\u45f2\u45f3\u45f4\u45f5\u45f6\u45f7\u45f8\u45f9\u45fa\u45fb\u45fc\u45fd\u45fe\u45ff\u4600\u4601\u4602\u4603\u4604\u4605\u4606\u4607\u4608\u4609\u460a\u460b\u460c\u460d\u460e\u460f\u4610\u4611\u4612\u4613\u4614\u4615\u4616\u4617\u4618\u4619\u461a\u461b\u461c\u461d\u461e\u461f\u4620\u4621\u4622\u4623\u4624\u4625\u4626\u4627\u4628\u4629\u462a\u462b\u462c\u462d\u462e\u462f\u4630\u4631\u4632\u4633\u4634\u4635\u4636\u4637\u4638\u4639\u463a\u463b\u463c\u463d\u463e\u463f\u4640\u4641\u4642\u4643\u4644\u4645\u4646\u4647\u4648\u4649\u464a\u464b\u464c\u464d\u464e\u464f\u4650\u4651\u4652\u4653\u4654\u4655\u4656\u4657\u4658\u4659\u465a\u465b\u465c\u465d\u465e\u465f\u4660\u4661\u4662\u4663\u4664\u4665\u4666\u4667\u4668\u4669\u466a\u466b\u466c\u466d\u466e\u466f\u4670\u4671\u4672\u4673\u4674\u4675\u4676\u4677\u4678\u4679\u467a\u467b\u467c\u467d\u467e\u467f\u4680\u4681\u4682\u4683\u4684\u4685\u4686\u4687\u4688\u4689\u468a\u468b\u468c\u468d\u468e\u468f\u4690\u4691\u4692\u4693\u4694\u4695\u4696\u4697\u4698\u4699\u469a\u469b\u469c\u469d\u469e\u469f\u46a0\u46a1\u46a2\u46a3\u46a4\u46a5\u46a6\u46a7\u46a8\u46a9\u46aa\u46ab\u46ac\u46ad\u46ae\u46af\u46b0\u46b1\u46b2\u46b3\u46b4\u46b5\u46b6\u46b7\u46b8\u46b9\u46ba\u46bb\u46bc\u46bd\u46be\u46bf\u46c0\u46c1\u46c2\u46c3\u46c4\u46c5\u46c6\u46c7\u46c8\u46c9\u46ca\u46cb\u46cc\u46cd\u46ce\u46cf\u46d0\u46d1\u46d2\u46d3\u46d4\u46d5\u46d6\u46d7\u46d8\u46d9\u46da\u46db\u46dc\u46dd\u46de\u46df\u46e0\u46e1\u46e2\u46e3\u46e4\u46e5\u46e6\u46e7\u46e8\u46e9\u46ea\u46eb\u46ec\u46ed\u46ee\u46ef\u46f0\u46f1\u46f2\u46f3\u46f4\u46f5\u46f6\u46f7\u46f8\u46f9\u46fa\u46fb\u46fc\u46fd\u46fe\u46ff\u4700\u4701\u4702\u4703\u4704\u4705\u4706\u4707\u4708\u4709\u470a\u470b\u470c\u470d\u470e\u470f\u4710\u4711\u4712\u4713\u4714\u4715\u4716\u4717\u4718\u4719\u471a\u471b\u471c\u471d\u471e\u471f\u4720\u4721\u4722\u4723\u4724\u4725\u4726\u4727\u4728\u4729\u472a\u472b\u472c\u472d\u472e\u472f\u4730\u4731\u4732\u4733\u4734\u4735\u4736\u4737\u4738\u4739\u473a\u473b\u473c\u473d\u473e\u473f\u4740\u4741\u4742\u4743\u4744\u4745\u4746\u4747\u4748\u4749\u474a\u474b\u474c\u474d\u474e\u474f\u4750\u4751\u4752\u4753\u4754\u4755\u4756\u4757\u4758\u4759\u475a\u475b\u475c\u475d\u475e\u475f\u4760\u4761\u4762\u4763\u4764\u4765\u4766\u4767\u4768\u4769\u476a\u476b\u476c\u476d\u476e\u476f\u4770\u4771\u4772\u4773\u4774\u4775\u4776\u4777\u4778\u4779\u477a\u477b\u477c\u477d\u477e\u477f\u4780\u4781\u4782\u4783\u4784\u4785\u4786\u4787\u4788\u4789\u478a\u478b\u478c\u478d\u478e\u478f\u4790\u4791\u4792\u4793\u4794\u4795\u4796\u4797\u4798\u4799\u479a\u479b\u479c\u479d\u479e\u479f\u47a0\u47a1\u47a2\u47a3\u47a4\u47a5\u47a6\u47a7\u47a8\u47a9\u47aa\u47ab\u47ac\u47ad\u47ae\u47af\u47b0\u47b1\u47b2\u47b3\u47b4\u47b5\u47b6\u47b7\u47b8\u47b9\u47ba\u47bb\u47bc\u47bd\u47be\u47bf\u47c0\u47c1\u47c2\u47c3\u47c4\u47c5\u47c6\u47c7\u47c8\u47c9\u47ca\u47cb\u47cc\u47cd\u47ce\u47cf\u47d0\u47d1\u47d2\u47d3\u47d4\u47d5\u47d6\u47d7\u47d8\u47d9\u47da\u47db\u47dc\u47dd\u47de\u47df\u47e0\u47e1\u47e2\u47e3\u47e4\u47e5\u47e6\u47e7\u47e8\u47e9\u47ea\u47eb\u47ec\u47ed\u47ee\u47ef\u47f0\u47f1\u47f2\u47f3\u47f4\u47f5\u47f6\u47f7\u47f8\u47f9\u47fa\u47fb\u47fc\u47fd\u47fe\u47ff\u4800\u4801\u4802\u4803\u4804\u4805\u4806\u4807\u4808\u4809\u480a\u480b\u480c\u480d\u480e\u480f\u4810\u4811\u4812\u4813\u4814\u4815\u4816\u4817\u4818\u4819\u481a\u481b\u481c\u481d\u481e\u481f\u4820\u4821\u4822\u4823\u4824\u4825\u4826\u4827\u4828\u4829\u482a\u482b\u482c\u482d\u482e\u482f\u4830\u4831\u4832\u4833\u4834\u4835\u4836\u4837\u4838\u4839\u483a\u483b\u483c\u483d\u483e\u483f\u4840\u4841\u4842\u4843\u4844\u4845\u4846\u4847\u4848\u4849\u484a\u484b\u484c\u484d\u484e\u484f\u4850\u4851\u4852\u4853\u4854\u4855\u4856\u4857\u4858\u4859\u485a\u485b\u485c\u485d\u485e\u485f\u4860\u4861\u4862\u4863\u4864\u4865\u4866\u4867\u4868\u4869\u486a\u486b\u486c\u486d\u486e\u486f\u4870\u4871\u4872\u4873\u4874\u4875\u4876\u4877\u4878\u4879\u487a\u487b\u487c\u487d\u487e\u487f\u4880\u4881\u4882\u4883\u4884\u4885\u4886\u4887\u4888\u4889\u488a\u488b\u488c\u488d\u488e\u488f\u4890\u4891\u4892\u4893\u4894\u4895\u4896\u4897\u4898\u4899\u489a\u489b\u489c\u489d\u489e\u489f\u48a0\u48a1\u48a2\u48a3\u48a4\u48a5\u48a6\u48a7\u48a8\u48a9\u48aa\u48ab\u48ac\u48ad\u48ae\u48af\u48b0\u48b1\u48b2\u48b3\u48b4\u48b5\u48b6\u48b7\u48b8\u48b9\u48ba\u48bb\u48bc\u48bd\u48be\u48bf\u48c0\u48c1\u48c2\u48c3\u48c4\u48c5\u48c6\u48c7\u48c8\u48c9\u48ca\u48cb\u48cc\u48cd\u48ce\u48cf\u48d0\u48d1\u48d2\u48d3\u48d4\u48d5\u48d6\u48d7\u48d8\u48d9\u48da\u48db\u48dc\u48dd\u48de\u48df\u48e0\u48e1\u48e2\u48e3\u48e4\u48e5\u48e6\u48e7\u48e8\u48e9\u48ea\u48eb\u48ec\u48ed\u48ee\u48ef\u48f0\u48f1\u48f2\u48f3\u48f4\u48f5\u48f6\u48f7\u48f8\u48f9\u48fa\u48fb\u48fc\u48fd\u48fe\u48ff\u4900\u4901\u4902\u4903\u4904\u4905\u4906\u4907\u4908\u4909\u490a\u490b\u490c\u490d\u490e\u490f\u4910\u4911\u4912\u4913\u4914\u4915\u4916\u4917\u4918\u4919\u491a\u491b\u491c\u491d\u491e\u491f\u4920\u4921\u4922\u4923\u4924\u4925\u4926\u4927\u4928\u4929\u492a\u492b\u492c\u492d\u492e\u492f\u4930\u4931\u4932\u4933\u4934\u4935\u4936\u4937\u4938\u4939\u493a\u493b\u493c\u493d\u493e\u493f\u4940\u4941\u4942\u4943\u4944\u4945\u4946\u4947\u4948\u4949\u494a\u494b\u494c\u494d\u494e\u494f\u4950\u4951\u4952\u4953\u4954\u4955\u4956\u4957\u4958\u4959\u495a\u495b\u495c\u495d\u495e\u495f\u4960\u4961\u4962\u4963\u4964\u4965\u4966\u4967\u4968\u4969\u496a\u496b\u496c\u496d\u496e\u496f\u4970\u4971\u4972\u4973\u4974\u4975\u4976\u4977\u4978\u4979\u497a\u497b\u497c\u497d\u497e\u497f\u4980\u4981\u4982\u4983\u4984\u4985\u4986\u4987\u4988\u4989\u498a\u498b\u498c\u498d\u498e\u498f\u4990\u4991\u4992\u4993\u4994\u4995\u4996\u4997\u4998\u4999\u499a\u499b\u499c\u499d\u499e\u499f\u49a0\u49a1\u49a2\u49a3\u49a4\u49a5\u49a6\u49a7\u49a8\u49a9\u49aa\u49ab\u49ac\u49ad\u49ae\u49af\u49b0\u49b1\u49b2\u49b3\u49b4\u49b5\u49b6\u49b7\u49b8\u49b9\u49ba\u49bb\u49bc\u49bd\u49be\u49bf\u49c0\u49c1\u49c2\u49c3\u49c4\u49c5\u49c6\u49c7\u49c8\u49c9\u49ca\u49cb\u49cc\u49cd\u49ce\u49cf\u49d0\u49d1\u49d2\u49d3\u49d4\u49d5\u49d6\u49d7\u49d8\u49d9\u49da\u49db\u49dc\u49dd\u49de\u49df\u49e0\u49e1\u49e2\u49e3\u49e4\u49e5\u49e6\u49e7\u49e8\u49e9\u49ea\u49eb\u49ec\u49ed\u49ee\u49ef\u49f0\u49f1\u49f2\u49f3\u49f4\u49f5\u49f6\u49f7\u49f8\u49f9\u49fa\u49fb\u49fc\u49fd\u49fe\u49ff\u4a00\u4a01\u4a02\u4a03\u4a04\u4a05\u4a06\u4a07\u4a08\u4a09\u4a0a\u4a0b\u4a0c\u4a0d\u4a0e\u4a0f\u4a10\u4a11\u4a12\u4a13\u4a14\u4a15\u4a16\u4a17\u4a18\u4a19\u4a1a\u4a1b\u4a1c\u4a1d\u4a1e\u4a1f\u4a20\u4a21\u4a22\u4a23\u4a24\u4a25\u4a26\u4a27\u4a28\u4a29\u4a2a\u4a2b\u4a2c\u4a2d\u4a2e\u4a2f\u4a30\u4a31\u4a32\u4a33\u4a34\u4a35\u4a36\u4a37\u4a38\u4a39\u4a3a\u4a3b\u4a3c\u4a3d\u4a3e\u4a3f\u4a40\u4a41\u4a42\u4a43\u4a44\u4a45\u4a46\u4a47\u4a48\u4a49\u4a4a\u4a4b\u4a4c\u4a4d\u4a4e\u4a4f\u4a50\u4a51\u4a52\u4a53\u4a54\u4a55\u4a56\u4a57\u4a58\u4a59\u4a5a\u4a5b\u4a5c\u4a5d\u4a5e\u4a5f\u4a60\u4a61\u4a62\u4a63\u4a64\u4a65\u4a66\u4a67\u4a68\u4a69\u4a6a\u4a6b\u4a6c\u4a6d\u4a6e\u4a6f\u4a70\u4a71\u4a72\u4a73\u4a74\u4a75\u4a76\u4a77\u4a78\u4a79\u4a7a\u4a7b\u4a7c\u4a7d\u4a7e\u4a7f\u4a80\u4a81\u4a82\u4a83\u4a84\u4a85\u4a86\u4a87\u4a88\u4a89\u4a8a\u4a8b\u4a8c\u4a8d\u4a8e\u4a8f\u4a90\u4a91\u4a92\u4a93\u4a94\u4a95\u4a96\u4a97\u4a98\u4a99\u4a9a\u4a9b\u4a9c\u4a9d\u4a9e\u4a9f\u4aa0\u4aa1\u4aa2\u4aa3\u4aa4\u4aa5\u4aa6\u4aa7\u4aa8\u4aa9\u4aaa\u4aab\u4aac\u4aad\u4aae\u4aaf\u4ab0\u4ab1\u4ab2\u4ab3\u4ab4\u4ab5\u4ab6\u4ab7\u4ab8\u4ab9\u4aba\u4abb\u4abc\u4abd\u4abe\u4abf\u4ac0\u4ac1\u4ac2\u4ac3\u4ac4\u4ac5\u4ac6\u4ac7\u4ac8\u4ac9\u4aca\u4acb\u4acc\u4acd\u4ace\u4acf\u4ad0\u4ad1\u4ad2\u4ad3\u4ad4\u4ad5\u4ad6\u4ad7\u4ad8\u4ad9\u4ada\u4adb\u4adc\u4add\u4ade\u4adf\u4ae0\u4ae1\u4ae2\u4ae3\u4ae4\u4ae5\u4ae6\u4ae7\u4ae8\u4ae9\u4aea\u4aeb\u4aec\u4aed\u4aee\u4aef\u4af0\u4af1\u4af2\u4af3\u4af4\u4af5\u4af6\u4af7\u4af8\u4af9\u4afa\u4afb\u4afc\u4afd\u4afe\u4aff\u4b00\u4b01\u4b02\u4b03\u4b04\u4b05\u4b06\u4b07\u4b08\u4b09\u4b0a\u4b0b\u4b0c\u4b0d\u4b0e\u4b0f\u4b10\u4b11\u4b12\u4b13\u4b14\u4b15\u4b16\u4b17\u4b18\u4b19\u4b1a\u4b1b\u4b1c\u4b1d\u4b1e\u4b1f\u4b20\u4b21\u4b22\u4b23\u4b24\u4b25\u4b26\u4b27\u4b28\u4b29\u4b2a\u4b2b\u4b2c\u4b2d\u4b2e\u4b2f\u4b30\u4b31\u4b32\u4b33\u4b34\u4b35\u4b36\u4b37\u4b38\u4b39\u4b3a\u4b3b\u4b3c\u4b3d\u4b3e\u4b3f\u4b40\u4b41\u4b42\u4b43\u4b44\u4b45\u4b46\u4b47\u4b48\u4b49\u4b4a\u4b4b\u4b4c\u4b4d\u4b4e\u4b4f\u4b50\u4b51\u4b52\u4b53\u4b54\u4b55\u4b56\u4b57\u4b58\u4b59\u4b5a\u4b5b\u4b5c\u4b5d\u4b5e\u4b5f\u4b60\u4b61\u4b62\u4b63\u4b64\u4b65\u4b66\u4b67\u4b68\u4b69\u4b6a\u4b6b\u4b6c\u4b6d\u4b6e\u4b6f\u4b70\u4b71\u4b72\u4b73\u4b74\u4b75\u4b76\u4b77\u4b78\u4b79\u4b7a\u4b7b\u4b7c\u4b7d\u4b7e\u4b7f\u4b80\u4b81\u4b82\u4b83\u4b84\u4b85\u4b86\u4b87\u4b88\u4b89\u4b8a\u4b8b\u4b8c\u4b8d\u4b8e\u4b8f\u4b90\u4b91\u4b92\u4b93\u4b94\u4b95\u4b96\u4b97\u4b98\u4b99\u4b9a\u4b9b\u4b9c\u4b9d\u4b9e\u4b9f\u4ba0\u4ba1\u4ba2\u4ba3\u4ba4\u4ba5\u4ba6\u4ba7\u4ba8\u4ba9\u4baa\u4bab\u4bac\u4bad\u4bae\u4baf\u4bb0\u4bb1\u4bb2\u4bb3\u4bb4\u4bb5\u4bb6\u4bb7\u4bb8\u4bb9\u4bba\u4bbb\u4bbc\u4bbd\u4bbe\u4bbf\u4bc0\u4bc1\u4bc2\u4bc3\u4bc4\u4bc5\u4bc6\u4bc7\u4bc8\u4bc9\u4bca\u4bcb\u4bcc\u4bcd\u4bce\u4bcf\u4bd0\u4bd1\u4bd2\u4bd3\u4bd4\u4bd5\u4bd6\u4bd7\u4bd8\u4bd9\u4bda\u4bdb\u4bdc\u4bdd\u4bde\u4bdf\u4be0\u4be1\u4be2\u4be3\u4be4\u4be5\u4be6\u4be7\u4be8\u4be9\u4bea\u4beb\u4bec\u4bed\u4bee\u4bef\u4bf0\u4bf1\u4bf2\u4bf3\u4bf4\u4bf5\u4bf6\u4bf7\u4bf8\u4bf9\u4bfa\u4bfb\u4bfc\u4bfd\u4bfe\u4bff\u4c00\u4c01\u4c02\u4c03\u4c04\u4c05\u4c06\u4c07\u4c08\u4c09\u4c0a\u4c0b\u4c0c\u4c0d\u4c0e\u4c0f\u4c10\u4c11\u4c12\u4c13\u4c14\u4c15\u4c16\u4c17\u4c18\u4c19\u4c1a\u4c1b\u4c1c\u4c1d\u4c1e\u4c1f\u4c20\u4c21\u4c22\u4c23\u4c24\u4c25\u4c26\u4c27\u4c28\u4c29\u4c2a\u4c2b\u4c2c\u4c2d\u4c2e\u4c2f\u4c30\u4c31\u4c32\u4c33\u4c34\u4c35\u4c36\u4c37\u4c38\u4c39\u4c3a\u4c3b\u4c3c\u4c3d\u4c3e\u4c3f\u4c40\u4c41\u4c42\u4c43\u4c44\u4c45\u4c46\u4c47\u4c48\u4c49\u4c4a\u4c4b\u4c4c\u4c4d\u4c4e\u4c4f\u4c50\u4c51\u4c52\u4c53\u4c54\u4c55\u4c56\u4c57\u4c58\u4c59\u4c5a\u4c5b\u4c5c\u4c5d\u4c5e\u4c5f\u4c60\u4c61\u4c62\u4c63\u4c64\u4c65\u4c66\u4c67\u4c68\u4c69\u4c6a\u4c6b\u4c6c\u4c6d\u4c6e\u4c6f\u4c70\u4c71\u4c72\u4c73\u4c74\u4c75\u4c76\u4c77\u4c78\u4c79\u4c7a\u4c7b\u4c7c\u4c7d\u4c7e\u4c7f\u4c80\u4c81\u4c82\u4c83\u4c84\u4c85\u4c86\u4c87\u4c88\u4c89\u4c8a\u4c8b\u4c8c\u4c8d\u4c8e\u4c8f\u4c90\u4c91\u4c92\u4c93\u4c94\u4c95\u4c96\u4c97\u4c98\u4c99\u4c9a\u4c9b\u4c9c\u4c9d\u4c9e\u4c9f\u4ca0\u4ca1\u4ca2\u4ca3\u4ca4\u4ca5\u4ca6\u4ca7\u4ca8\u4ca9\u4caa\u4cab\u4cac\u4cad\u4cae\u4caf\u4cb0\u4cb1\u4cb2\u4cb3\u4cb4\u4cb5\u4cb6\u4cb7\u4cb8\u4cb9\u4cba\u4cbb\u4cbc\u4cbd\u4cbe\u4cbf\u4cc0\u4cc1\u4cc2\u4cc3\u4cc4\u4cc5\u4cc6\u4cc7\u4cc8\u4cc9\u4cca\u4ccb\u4ccc\u4ccd\u4cce\u4ccf\u4cd0\u4cd1\u4cd2\u4cd3\u4cd4\u4cd5\u4cd6\u4cd7\u4cd8\u4cd9\u4cda\u4cdb\u4cdc\u4cdd\u4cde\u4cdf\u4ce0\u4ce1\u4ce2\u4ce3\u4ce4\u4ce5\u4ce6\u4ce7\u4ce8\u4ce9\u4cea\u4ceb\u4cec\u4ced\u4cee\u4cef\u4cf0\u4cf1\u4cf2\u4cf3\u4cf4\u4cf5\u4cf6\u4cf7\u4cf8\u4cf9\u4cfa\u4cfb\u4cfc\u4cfd\u4cfe\u4cff\u4d00\u4d01\u4d02\u4d03\u4d04\u4d05\u4d06\u4d07\u4d08\u4d09\u4d0a\u4d0b\u4d0c\u4d0d\u4d0e\u4d0f\u4d10\u4d11\u4d12\u4d13\u4d14\u4d15\u4d16\u4d17\u4d18\u4d19\u4d1a\u4d1b\u4d1c\u4d1d\u4d1e\u4d1f\u4d20\u4d21\u4d22\u4d23\u4d24\u4d25\u4d26\u4d27\u4d28\u4d29\u4d2a\u4d2b\u4d2c\u4d2d\u4d2e\u4d2f\u4d30\u4d31\u4d32\u4d33\u4d34\u4d35\u4d36\u4d37\u4d38\u4d39\u4d3a\u4d3b\u4d3c\u4d3d\u4d3e\u4d3f\u4d40\u4d41\u4d42\u4d43\u4d44\u4d45\u4d46\u4d47\u4d48\u4d49\u4d4a\u4d4b\u4d4c\u4d4d\u4d4e\u4d4f\u4d50\u4d51\u4d52\u4d53\u4d54\u4d55\u4d56\u4d57\u4d58\u4d59\u4d5a\u4d5b\u4d5c\u4d5d\u4d5e\u4d5f\u4d60\u4d61\u4d62\u4d63\u4d64\u4d65\u4d66\u4d67\u4d68\u4d69\u4d6a\u4d6b\u4d6c\u4d6d\u4d6e\u4d6f\u4d70\u4d71\u4d72\u4d73\u4d74\u4d75\u4d76\u4d77\u4d78\u4d79\u4d7a\u4d7b\u4d7c\u4d7d\u4d7e\u4d7f\u4d80\u4d81\u4d82\u4d83\u4d84\u4d85\u4d86\u4d87\u4d88\u4d89\u4d8a\u4d8b\u4d8c\u4d8d\u4d8e\u4d8f\u4d90\u4d91\u4d92\u4d93\u4d94\u4d95\u4d96\u4d97\u4d98\u4d99\u4d9a\u4d9b\u4d9c\u4d9d\u4d9e\u4d9f\u4da0\u4da1\u4da2\u4da3\u4da4\u4da5\u4da6\u4da7\u4da8\u4da9\u4daa\u4dab\u4dac\u4dad\u4dae\u4daf\u4db0\u4db1\u4db2\u4db3\u4db4\u4db5\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08\u4e09\u4e0a\u4e0b\u4e0c\u4e0d\u4e0e\u4e0f\u4e10\u4e11\u4e12\u4e13\u4e14\u4e15\u4e16\u4e17\u4e18\u4e19\u4e1a\u4e1b\u4e1c\u4e1d\u4e1e\u4e1f\u4e20\u4e21\u4e22\u4e23\u4e24\u4e25\u4e26\u4e27\u4e28\u4e29\u4e2a\u4e2b\u4e2c\u4e2d\u4e2e\u4e2f\u4e30\u4e31\u4e32\u4e33\u4e34\u4e35\u4e36\u4e37\u4e38\u4e39\u4e3a\u4e3b\u4e3c\u4e3d\u4e3e\u4e3f\u4e40\u4e41\u4e42\u4e43\u4e44\u4e45\u4e46\u4e47\u4e48\u4e49\u4e4a\u4e4b\u4e4c\u4e4d\u4e4e\u4e4f\u4e50\u4e51\u4e52\u4e53\u4e54\u4e55\u4e56\u4e57\u4e58\u4e59\u4e5a\u4e5b\u4e5c\u4e5d\u4e5e\u4e5f\u4e60\u4e61\u4e62\u4e63\u4e64\u4e65\u4e66\u4e67\u4e68\u4e69\u4e6a\u4e6b\u4e6c\u4e6d\u4e6e\u4e6f\u4e70\u4e71\u4e72\u4e73\u4e74\u4e75\u4e76\u4e77\u4e78\u4e79\u4e7a\u4e7b\u4e7c\u4e7d\u4e7e\u4e7f\u4e80\u4e81\u4e82\u4e83\u4e84\u4e85\u4e86\u4e87\u4e88\u4e89\u4e8a\u4e8b\u4e8c\u4e8d\u4e8e\u4e8f\u4e90\u4e91\u4e92\u4e93\u4e94\u4e95\u4e96\u4e97\u4e98\u4e99\u4e9a\u4e9b\u4e9c\u4e9d\u4e9e\u4e9f\u4ea0\u4ea1\u4ea2\u4ea3\u4ea4\u4ea5\u4ea6\u4ea7\u4ea8\u4ea9\u4eaa\u4eab\u4eac\u4ead\u4eae\u4eaf\u4eb0\u4eb1\u4eb2\u4eb3\u4eb4\u4eb5\u4eb6\u4eb7\u4eb8\u4eb9\u4eba\u4ebb\u4ebc\u4ebd\u4ebe\u4ebf\u4ec0\u4ec1\u4ec2\u4ec3\u4ec4\u4ec5\u4ec6\u4ec7\u4ec8\u4ec9\u4eca\u4ecb\u4ecc\u4ecd\u4ece\u4ecf\u4ed0\u4ed1\u4ed2\u4ed3\u4ed4\u4ed5\u4ed6\u4ed7\u4ed8\u4ed9\u4eda\u4edb\u4edc\u4edd\u4ede\u4edf\u4ee0\u4ee1\u4ee2\u4ee3\u4ee4\u4ee5\u4ee6\u4ee7\u4ee8\u4ee9\u4eea\u4eeb\u4eec\u4eed\u4eee\u4eef\u4ef0\u4ef1\u4ef2\u4ef3\u4ef4\u4ef5\u4ef6\u4ef7\u4ef8\u4ef9\u4efa\u4efb\u4efc\u4efd\u4efe\u4eff\u4f00\u4f01\u4f02\u4f03\u4f04\u4f05\u4f06\u4f07\u4f08\u4f09\u4f0a\u4f0b\u4f0c\u4f0d\u4f0e\u4f0f\u4f10\u4f11\u4f12\u4f13\u4f14\u4f15\u4f16\u4f17\u4f18\u4f19\u4f1a\u4f1b\u4f1c\u4f1d\u4f1e\u4f1f\u4f20\u4f21\u4f22\u4f23\u4f24\u4f25\u4f26\u4f27\u4f28\u4f29\u4f2a\u4f2b\u4f2c\u4f2d\u4f2e\u4f2f\u4f30\u4f31\u4f32\u4f33\u4f34\u4f35\u4f36\u4f37\u4f38\u4f39\u4f3a\u4f3b\u4f3c\u4f3d\u4f3e\u4f3f\u4f40\u4f41\u4f42\u4f43\u4f44\u4f45\u4f46\u4f47\u4f48\u4f49\u4f4a\u4f4b\u4f4c\u4f4d\u4f4e\u4f4f\u4f50\u4f51\u4f52\u4f53\u4f54\u4f55\u4f56\u4f57\u4f58\u4f59\u4f5a\u4f5b\u4f5c\u4f5d\u4f5e\u4f5f\u4f60\u4f61\u4f62\u4f63\u4f64\u4f65\u4f66\u4f67\u4f68\u4f69\u4f6a\u4f6b\u4f6c\u4f6d\u4f6e\u4f6f\u4f70\u4f71\u4f72\u4f73\u4f74\u4f75\u4f76\u4f77\u4f78\u4f79\u4f7a\u4f7b\u4f7c\u4f7d\u4f7e\u4f7f\u4f80\u4f81\u4f82\u4f83\u4f84\u4f85\u4f86\u4f87\u4f88\u4f89\u4f8a\u4f8b\u4f8c\u4f8d\u4f8e\u4f8f\u4f90\u4f91\u4f92\u4f93\u4f94\u4f95\u4f96\u4f97\u4f98\u4f99\u4f9a\u4f9b\u4f9c\u4f9d\u4f9e\u4f9f\u4fa0\u4fa1\u4fa2\u4fa3\u4fa4\u4fa5\u4fa6\u4fa7\u4fa8\u4fa9\u4faa\u4fab\u4fac\u4fad\u4fae\u4faf\u4fb0\u4fb1\u4fb2\u4fb3\u4fb4\u4fb5\u4fb6\u4fb7\u4fb8\u4fb9\u4fba\u4fbb\u4fbc\u4fbd\u4fbe\u4fbf\u4fc0\u4fc1\u4fc2\u4fc3\u4fc4\u4fc5\u4fc6\u4fc7\u4fc8\u4fc9\u4fca\u4fcb\u4fcc\u4fcd\u4fce\u4fcf\u4fd0\u4fd1\u4fd2\u4fd3\u4fd4\u4fd5\u4fd6\u4fd7\u4fd8\u4fd9\u4fda\u4fdb\u4fdc\u4fdd\u4fde\u4fdf\u4fe0\u4fe1\u4fe2\u4fe3\u4fe4\u4fe5\u4fe6\u4fe7\u4fe8\u4fe9\u4fea\u4feb\u4fec\u4fed\u4fee\u4fef\u4ff0\u4ff1\u4ff2\u4ff3\u4ff4\u4ff5\u4ff6\u4ff7\u4ff8\u4ff9\u4ffa\u4ffb\u4ffc\u4ffd\u4ffe\u4fff\u5000\u5001\u5002\u5003\u5004\u5005\u5006\u5007\u5008\u5009\u500a\u500b\u500c\u500d\u500e\u500f\u5010\u5011\u5012\u5013\u5014\u5015\u5016\u5017\u5018\u5019\u501a\u501b\u501c\u501d\u501e\u501f\u5020\u5021\u5022\u5023\u5024\u5025\u5026\u5027\u5028\u5029\u502a\u502b\u502c\u502d\u502e\u502f\u5030\u5031\u5032\u5033\u5034\u5035\u5036\u5037\u5038\u5039\u503a\u503b\u503c\u503d\u503e\u503f\u5040\u5041\u5042\u5043\u5044\u5045\u5046\u5047\u5048\u5049\u504a\u504b\u504c\u504d\u504e\u504f\u5050\u5051\u5052\u5053\u5054\u5055\u5056\u5057\u5058\u5059\u505a\u505b\u505c\u505d\u505e\u505f\u5060\u5061\u5062\u5063\u5064\u5065\u5066\u5067\u5068\u5069\u506a\u506b\u506c\u506d\u506e\u506f\u5070\u5071\u5072\u5073\u5074\u5075\u5076\u5077\u5078\u5079\u507a\u507b\u507c\u507d\u507e\u507f\u5080\u5081\u5082\u5083\u5084\u5085\u5086\u5087\u5088\u5089\u508a\u508b\u508c\u508d\u508e\u508f\u5090\u5091\u5092\u5093\u5094\u5095\u5096\u5097\u5098\u5099\u509a\u509b\u509c\u509d\u509e\u509f\u50a0\u50a1\u50a2\u50a3\u50a4\u50a5\u50a6\u50a7\u50a8\u50a9\u50aa\u50ab\u50ac\u50ad\u50ae\u50af\u50b0\u50b1\u50b2\u50b3\u50b4\u50b5\u50b6\u50b7\u50b8\u50b9\u50ba\u50bb\u50bc\u50bd\u50be\u50bf\u50c0\u50c1\u50c2\u50c3\u50c4\u50c5\u50c6\u50c7\u50c8\u50c9\u50ca\u50cb\u50cc\u50cd\u50ce\u50cf\u50d0\u50d1\u50d2\u50d3\u50d4\u50d5\u50d6\u50d7\u50d8\u50d9\u50da\u50db\u50dc\u50dd\u50de\u50df\u50e0\u50e1\u50e2\u50e3\u50e4\u50e5\u50e6\u50e7\u50e8\u50e9\u50ea\u50eb\u50ec\u50ed\u50ee\u50ef\u50f0\u50f1\u50f2\u50f3\u50f4\u50f5\u50f6\u50f7\u50f8\u50f9\u50fa\u50fb\u50fc\u50fd\u50fe\u50ff\u5100\u5101\u5102\u5103\u5104\u5105\u5106\u5107\u5108\u5109\u510a\u510b\u510c\u510d\u510e\u510f\u5110\u5111\u5112\u5113\u5114\u5115\u5116\u5117\u5118\u5119\u511a\u511b\u511c\u511d\u511e\u511f\u5120\u5121\u5122\u5123\u5124\u5125\u5126\u5127\u5128\u5129\u512a\u512b\u512c\u512d\u512e\u512f\u5130\u5131\u5132\u5133\u5134\u5135\u5136\u5137\u5138\u5139\u513a\u513b\u513c\u513d\u513e\u513f\u5140\u5141\u5142\u5143\u5144\u5145\u5146\u5147\u5148\u5149\u514a\u514b\u514c\u514d\u514e\u514f\u5150\u5151\u5152\u5153\u5154\u5155\u5156\u5157\u5158\u5159\u515a\u515b\u515c\u515d\u515e\u515f\u5160\u5161\u5162\u5163\u5164\u5165\u5166\u5167\u5168\u5169\u516a\u516b\u516c\u516d\u516e\u516f\u5170\u5171\u5172\u5173\u5174\u5175\u5176\u5177\u5178\u5179\u517a\u517b\u517c\u517d\u517e\u517f\u5180\u5181\u5182\u5183\u5184\u5185\u5186\u5187\u5188\u5189\u518a\u518b\u518c\u518d\u518e\u518f\u5190\u5191\u5192\u5193\u5194\u5195\u5196\u5197\u5198\u5199\u519a\u519b\u519c\u519d\u519e\u519f\u51a0\u51a1\u51a2\u51a3\u51a4\u51a5\u51a6\u51a7\u51a8\u51a9\u51aa\u51ab\u51ac\u51ad\u51ae\u51af\u51b0\u51b1\u51b2\u51b3\u51b4\u51b5\u51b6\u51b7\u51b8\u51b9\u51ba\u51bb\u51bc\u51bd\u51be\u51bf\u51c0\u51c1\u51c2\u51c3\u51c4\u51c5\u51c6\u51c7\u51c8\u51c9\u51ca\u51cb\u51cc\u51cd\u51ce\u51cf\u51d0\u51d1\u51d2\u51d3\u51d4\u51d5\u51d6\u51d7\u51d8\u51d9\u51da\u51db\u51dc\u51dd\u51de\u51df\u51e0\u51e1\u51e2\u51e3\u51e4\u51e5\u51e6\u51e7\u51e8\u51e9\u51ea\u51eb\u51ec\u51ed\u51ee\u51ef\u51f0\u51f1\u51f2\u51f3\u51f4\u51f5\u51f6\u51f7\u51f8\u51f9\u51fa\u51fb\u51fc\u51fd\u51fe\u51ff\u5200\u5201\u5202\u5203\u5204\u5205\u5206\u5207\u5208\u5209\u520a\u520b\u520c\u520d\u520e\u520f\u5210\u5211\u5212\u5213\u5214\u5215\u5216\u5217\u5218\u5219\u521a\u521b\u521c\u521d\u521e\u521f\u5220\u5221\u5222\u5223\u5224\u5225\u5226\u5227\u5228\u5229\u522a\u522b\u522c\u522d\u522e\u522f\u5230\u5231\u5232\u5233\u5234\u5235\u5236\u5237\u5238\u5239\u523a\u523b\u523c\u523d\u523e\u523f\u5240\u5241\u5242\u5243\u5244\u5245\u5246\u5247\u5248\u5249\u524a\u524b\u524c\u524d\u524e\u524f\u5250\u5251\u5252\u5253\u5254\u5255\u5256\u5257\u5258\u5259\u525a\u525b\u525c\u525d\u525e\u525f\u5260\u5261\u5262\u5263\u5264\u5265\u5266\u5267\u5268\u5269\u526a\u526b\u526c\u526d\u526e\u526f\u5270\u5271\u5272\u5273\u5274\u5275\u5276\u5277\u5278\u5279\u527a\u527b\u527c\u527d\u527e\u527f\u5280\u5281\u5282\u5283\u5284\u5285\u5286\u5287\u5288\u5289\u528a\u528b\u528c\u528d\u528e\u528f\u5290\u5291\u5292\u5293\u5294\u5295\u5296\u5297\u5298\u5299\u529a\u529b\u529c\u529d\u529e\u529f\u52a0\u52a1\u52a2\u52a3\u52a4\u52a5\u52a6\u52a7\u52a8\u52a9\u52aa\u52ab\u52ac\u52ad\u52ae\u52af\u52b0\u52b1\u52b2\u52b3\u52b4\u52b5\u52b6\u52b7\u52b8\u52b9\u52ba\u52bb\u52bc\u52bd\u52be\u52bf\u52c0\u52c1\u52c2\u52c3\u52c4\u52c5\u52c6\u52c7\u52c8\u52c9\u52ca\u52cb\u52cc\u52cd\u52ce\u52cf\u52d0\u52d1\u52d2\u52d3\u52d4\u52d5\u52d6\u52d7\u52d8\u52d9\u52da\u52db\u52dc\u52dd\u52de\u52df\u52e0\u52e1\u52e2\u52e3\u52e4\u52e5\u52e6\u52e7\u52e8\u52e9\u52ea\u52eb\u52ec\u52ed\u52ee\u52ef\u52f0\u52f1\u52f2\u52f3\u52f4\u52f5\u52f6\u52f7\u52f8\u52f9\u52fa\u52fb\u52fc\u52fd\u52fe\u52ff\u5300\u5301\u5302\u5303\u5304\u5305\u5306\u5307\u5308\u5309\u530a\u530b\u530c\u530d\u530e\u530f\u5310\u5311\u5312\u5313\u5314\u5315\u5316\u5317\u5318\u5319\u531a\u531b\u531c\u531d\u531e\u531f\u5320\u5321\u5322\u5323\u5324\u5325\u5326\u5327\u5328\u5329\u532a\u532b\u532c\u532d\u532e\u532f\u5330\u5331\u5332\u5333\u5334\u5335\u5336\u5337\u5338\u5339\u533a\u533b\u533c\u533d\u533e\u533f\u5340\u5341\u5342\u5343\u5344\u5345\u5346\u5347\u5348\u5349\u534a\u534b\u534c\u534d\u534e\u534f\u5350\u5351\u5352\u5353\u5354\u5355\u5356\u5357\u5358\u5359\u535a\u535b\u535c\u535d\u535e\u535f\u5360\u5361\u5362\u5363\u5364\u5365\u5366\u5367\u5368\u5369\u536a\u536b\u536c\u536d\u536e\u536f\u5370\u5371\u5372\u5373\u5374\u5375\u5376\u5377\u5378\u5379\u537a\u537b\u537c\u537d\u537e\u537f\u5380\u5381\u5382\u5383\u5384\u5385\u5386\u5387\u5388\u5389\u538a\u538b\u538c\u538d\u538e\u538f\u5390\u5391\u5392\u5393\u5394\u5395\u5396\u5397\u5398\u5399\u539a\u539b\u539c\u539d\u539e\u539f\u53a0\u53a1\u53a2\u53a3\u53a4\u53a5\u53a6\u53a7\u53a8\u53a9\u53aa\u53ab\u53ac\u53ad\u53ae\u53af\u53b0\u53b1\u53b2\u53b3\u53b4\u53b5\u53b6\u53b7\u53b8\u53b9\u53ba\u53bb\u53bc\u53bd\u53be\u53bf\u53c0\u53c1\u53c2\u53c3\u53c4\u53c5\u53c6\u53c7\u53c8\u53c9\u53ca\u53cb\u53cc\u53cd\u53ce\u53cf\u53d0\u53d1\u53d2\u53d3\u53d4\u53d5\u53d6\u53d7\u53d8\u53d9\u53da\u53db\u53dc\u53dd\u53de\u53df\u53e0\u53e1\u53e2\u53e3\u53e4\u53e5\u53e6\u53e7\u53e8\u53e9\u53ea\u53eb\u53ec\u53ed\u53ee\u53ef\u53f0\u53f1\u53f2\u53f3\u53f4\u53f5\u53f6\u53f7\u53f8\u53f9\u53fa\u53fb\u53fc\u53fd\u53fe\u53ff\u5400\u5401\u5402\u5403\u5404\u5405\u5406\u5407\u5408\u5409\u540a\u540b\u540c\u540d\u540e\u540f\u5410\u5411\u5412\u5413\u5414\u5415\u5416\u5417\u5418\u5419\u541a\u541b\u541c\u541d\u541e\u541f\u5420\u5421\u5422\u5423\u5424\u5425\u5426\u5427\u5428\u5429\u542a\u542b\u542c\u542d\u542e\u542f\u5430\u5431\u5432\u5433\u5434\u5435\u5436\u5437\u5438\u5439\u543a\u543b\u543c\u543d\u543e\u543f\u5440\u5441\u5442\u5443\u5444\u5445\u5446\u5447\u5448\u5449\u544a\u544b\u544c\u544d\u544e\u544f\u5450\u5451\u5452\u5453\u5454\u5455\u5456\u5457\u5458\u5459\u545a\u545b\u545c\u545d\u545e\u545f\u5460\u5461\u5462\u5463\u5464\u5465\u5466\u5467\u5468\u5469\u546a\u546b\u546c\u546d\u546e\u546f\u5470\u5471\u5472\u5473\u5474\u5475\u5476\u5477\u5478\u5479\u547a\u547b\u547c\u547d\u547e\u547f\u5480\u5481\u5482\u5483\u5484\u5485\u5486\u5487\u5488\u5489\u548a\u548b\u548c\u548d\u548e\u548f\u5490\u5491\u5492\u5493\u5494\u5495\u5496\u5497\u5498\u5499\u549a\u549b\u549c\u549d\u549e\u549f\u54a0\u54a1\u54a2\u54a3\u54a4\u54a5\u54a6\u54a7\u54a8\u54a9\u54aa\u54ab\u54ac\u54ad\u54ae\u54af\u54b0\u54b1\u54b2\u54b3\u54b4\u54b5\u54b6\u54b7\u54b8\u54b9\u54ba\u54bb\u54bc\u54bd\u54be\u54bf\u54c0\u54c1\u54c2\u54c3\u54c4\u54c5\u54c6\u54c7\u54c8\u54c9\u54ca\u54cb\u54cc\u54cd\u54ce\u54cf\u54d0\u54d1\u54d2\u54d3\u54d4\u54d5\u54d6\u54d7\u54d8\u54d9\u54da\u54db\u54dc\u54dd\u54de\u54df\u54e0\u54e1\u54e2\u54e3\u54e4\u54e5\u54e6\u54e7\u54e8\u54e9\u54ea\u54eb\u54ec\u54ed\u54ee\u54ef\u54f0\u54f1\u54f2\u54f3\u54f4\u54f5\u54f6\u54f7\u54f8\u54f9\u54fa\u54fb\u54fc\u54fd\u54fe\u54ff\u5500\u5501\u5502\u5503\u5504\u5505\u5506\u5507\u5508\u5509\u550a\u550b\u550c\u550d\u550e\u550f\u5510\u5511\u5512\u5513\u5514\u5515\u5516\u5517\u5518\u5519\u551a\u551b\u551c\u551d\u551e\u551f\u5520\u5521\u5522\u5523\u5524\u5525\u5526\u5527\u5528\u5529\u552a\u552b\u552c\u552d\u552e\u552f\u5530\u5531\u5532\u5533\u5534\u5535\u5536\u5537\u5538\u5539\u553a\u553b\u553c\u553d\u553e\u553f\u5540\u5541\u5542\u5543\u5544\u5545\u5546\u5547\u5548\u5549\u554a\u554b\u554c\u554d\u554e\u554f\u5550\u5551\u5552\u5553\u5554\u5555\u5556\u5557\u5558\u5559\u555a\u555b\u555c\u555d\u555e\u555f\u5560\u5561\u5562\u5563\u5564\u5565\u5566\u5567\u5568\u5569\u556a\u556b\u556c\u556d\u556e\u556f\u5570\u5571\u5572\u5573\u5574\u5575\u5576\u5577\u5578\u5579\u557a\u557b\u557c\u557d\u557e\u557f\u5580\u5581\u5582\u5583\u5584\u5585\u5586\u5587\u5588\u5589\u558a\u558b\u558c\u558d\u558e\u558f\u5590\u5591\u5592\u5593\u5594\u5595\u5596\u5597\u5598\u5599\u559a\u559b\u559c\u559d\u559e\u559f\u55a0\u55a1\u55a2\u55a3\u55a4\u55a5\u55a6\u55a7\u55a8\u55a9\u55aa\u55ab\u55ac\u55ad\u55ae\u55af\u55b0\u55b1\u55b2\u55b3\u55b4\u55b5\u55b6\u55b7\u55b8\u55b9\u55ba\u55bb\u55bc\u55bd\u55be\u55bf\u55c0\u55c1\u55c2\u55c3\u55c4\u55c5\u55c6\u55c7\u55c8\u55c9\u55ca\u55cb\u55cc\u55cd\u55ce\u55cf\u55d0\u55d1\u55d2\u55d3\u55d4\u55d5\u55d6\u55d7\u55d8\u55d9\u55da\u55db\u55dc\u55dd\u55de\u55df\u55e0\u55e1\u55e2\u55e3\u55e4\u55e5\u55e6\u55e7\u55e8\u55e9\u55ea\u55eb\u55ec\u55ed\u55ee\u55ef\u55f0\u55f1\u55f2\u55f3\u55f4\u55f5\u55f6\u55f7\u55f8\u55f9\u55fa\u55fb\u55fc\u55fd\u55fe\u55ff\u5600\u5601\u5602\u5603\u5604\u5605\u5606\u5607\u5608\u5609\u560a\u560b\u560c\u560d\u560e\u560f\u5610\u5611\u5612\u5613\u5614\u5615\u5616\u5617\u5618\u5619\u561a\u561b\u561c\u561d\u561e\u561f\u5620\u5621\u5622\u5623\u5624\u5625\u5626\u5627\u5628\u5629\u562a\u562b\u562c\u562d\u562e\u562f\u5630\u5631\u5632\u5633\u5634\u5635\u5636\u5637\u5638\u5639\u563a\u563b\u563c\u563d\u563e\u563f\u5640\u5641\u5642\u5643\u5644\u5645\u5646\u5647\u5648\u5649\u564a\u564b\u564c\u564d\u564e\u564f\u5650\u5651\u5652\u5653\u5654\u5655\u5656\u5657\u5658\u5659\u565a\u565b\u565c\u565d\u565e\u565f\u5660\u5661\u5662\u5663\u5664\u5665\u5666\u5667\u5668\u5669\u566a\u566b\u566c\u566d\u566e\u566f\u5670\u5671\u5672\u5673\u5674\u5675\u5676\u5677\u5678\u5679\u567a\u567b\u567c\u567d\u567e\u567f\u5680\u5681\u5682\u5683\u5684\u5685\u5686\u5687\u5688\u5689\u568a\u568b\u568c\u568d\u568e\u568f\u5690\u5691\u5692\u5693\u5694\u5695\u5696\u5697\u5698\u5699\u569a\u569b\u569c\u569d\u569e\u569f\u56a0\u56a1\u56a2\u56a3\u56a4\u56a5\u56a6\u56a7\u56a8\u56a9\u56aa\u56ab\u56ac\u56ad\u56ae\u56af\u56b0\u56b1\u56b2\u56b3\u56b4\u56b5\u56b6\u56b7\u56b8\u56b9\u56ba\u56bb\u56bc\u56bd\u56be\u56bf\u56c0\u56c1\u56c2\u56c3\u56c4\u56c5\u56c6\u56c7\u56c8\u56c9\u56ca\u56cb\u56cc\u56cd\u56ce\u56cf\u56d0\u56d1\u56d2\u56d3\u56d4\u56d5\u56d6\u56d7\u56d8\u56d9\u56da\u56db\u56dc\u56dd\u56de\u56df\u56e0\u56e1\u56e2\u56e3\u56e4\u56e5\u56e6\u56e7\u56e8\u56e9\u56ea\u56eb\u56ec\u56ed\u56ee\u56ef\u56f0\u56f1\u56f2\u56f3\u56f4\u56f5\u56f6\u56f7\u56f8\u56f9\u56fa\u56fb\u56fc\u56fd\u56fe\u56ff\u5700\u5701\u5702\u5703\u5704\u5705\u5706\u5707\u5708\u5709\u570a\u570b\u570c\u570d\u570e\u570f\u5710\u5711\u5712\u5713\u5714\u5715\u5716\u5717\u5718\u5719\u571a\u571b\u571c\u571d\u571e\u571f\u5720\u5721\u5722\u5723\u5724\u5725\u5726\u5727\u5728\u5729\u572a\u572b\u572c\u572d\u572e\u572f\u5730\u5731\u5732\u5733\u5734\u5735\u5736\u5737\u5738\u5739\u573a\u573b\u573c\u573d\u573e\u573f\u5740\u5741\u5742\u5743\u5744\u5745\u5746\u5747\u5748\u5749\u574a\u574b\u574c\u574d\u574e\u574f\u5750\u5751\u5752\u5753\u5754\u5755\u5756\u5757\u5758\u5759\u575a\u575b\u575c\u575d\u575e\u575f\u5760\u5761\u5762\u5763\u5764\u5765\u5766\u5767\u5768\u5769\u576a\u576b\u576c\u576d\u576e\u576f\u5770\u5771\u5772\u5773\u5774\u5775\u5776\u5777\u5778\u5779\u577a\u577b\u577c\u577d\u577e\u577f\u5780\u5781\u5782\u5783\u5784\u5785\u5786\u5787\u5788\u5789\u578a\u578b\u578c\u578d\u578e\u578f\u5790\u5791\u5792\u5793\u5794\u5795\u5796\u5797\u5798\u5799\u579a\u579b\u579c\u579d\u579e\u579f\u57a0\u57a1\u57a2\u57a3\u57a4\u57a5\u57a6\u57a7\u57a8\u57a9\u57aa\u57ab\u57ac\u57ad\u57ae\u57af\u57b0\u57b1\u57b2\u57b3\u57b4\u57b5\u57b6\u57b7\u57b8\u57b9\u57ba\u57bb\u57bc\u57bd\u57be\u57bf\u57c0\u57c1\u57c2\u57c3\u57c4\u57c5\u57c6\u57c7\u57c8\u57c9\u57ca\u57cb\u57cc\u57cd\u57ce\u57cf\u57d0\u57d1\u57d2\u57d3\u57d4\u57d5\u57d6\u57d7\u57d8\u57d9\u57da\u57db\u57dc\u57dd\u57de\u57df\u57e0\u57e1\u57e2\u57e3\u57e4\u57e5\u57e6\u57e7\u57e8\u57e9\u57ea\u57eb\u57ec\u57ed\u57ee\u57ef\u57f0\u57f1\u57f2\u57f3\u57f4\u57f5\u57f6\u57f7\u57f8\u57f9\u57fa\u57fb\u57fc\u57fd\u57fe\u57ff\u5800\u5801\u5802\u5803\u5804\u5805\u5806\u5807\u5808\u5809\u580a\u580b\u580c\u580d\u580e\u580f\u5810\u5811\u5812\u5813\u5814\u5815\u5816\u5817\u5818\u5819\u581a\u581b\u581c\u581d\u581e\u581f\u5820\u5821\u5822\u5823\u5824\u5825\u5826\u5827\u5828\u5829\u582a\u582b\u582c\u582d\u582e\u582f\u5830\u5831\u5832\u5833\u5834\u5835\u5836\u5837\u5838\u5839\u583a\u583b\u583c\u583d\u583e\u583f\u5840\u5841\u5842\u5843\u5844\u5845\u5846\u5847\u5848\u5849\u584a\u584b\u584c\u584d\u584e\u584f\u5850\u5851\u5852\u5853\u5854\u5855\u5856\u5857\u5858\u5859\u585a\u585b\u585c\u585d\u585e\u585f\u5860\u5861\u5862\u5863\u5864\u5865\u5866\u5867\u5868\u5869\u586a\u586b\u586c\u586d\u586e\u586f\u5870\u5871\u5872\u5873\u5874\u5875\u5876\u5877\u5878\u5879\u587a\u587b\u587c\u587d\u587e\u587f\u5880\u5881\u5882\u5883\u5884\u5885\u5886\u5887\u5888\u5889\u588a\u588b\u588c\u588d\u588e\u588f\u5890\u5891\u5892\u5893\u5894\u5895\u5896\u5897\u5898\u5899\u589a\u589b\u589c\u589d\u589e\u589f\u58a0\u58a1\u58a2\u58a3\u58a4\u58a5\u58a6\u58a7\u58a8\u58a9\u58aa\u58ab\u58ac\u58ad\u58ae\u58af\u58b0\u58b1\u58b2\u58b3\u58b4\u58b5\u58b6\u58b7\u58b8\u58b9\u58ba\u58bb\u58bc\u58bd\u58be\u58bf\u58c0\u58c1\u58c2\u58c3\u58c4\u58c5\u58c6\u58c7\u58c8\u58c9\u58ca\u58cb\u58cc\u58cd\u58ce\u58cf\u58d0\u58d1\u58d2\u58d3\u58d4\u58d5\u58d6\u58d7\u58d8\u58d9\u58da\u58db\u58dc\u58dd\u58de\u58df\u58e0\u58e1\u58e2\u58e3\u58e4\u58e5\u58e6\u58e7\u58e8\u58e9\u58ea\u58eb\u58ec\u58ed\u58ee\u58ef\u58f0\u58f1\u58f2\u58f3\u58f4\u58f5\u58f6\u58f7\u58f8\u58f9\u58fa\u58fb\u58fc\u58fd\u58fe\u58ff\u5900\u5901\u5902\u5903\u5904\u5905\u5906\u5907\u5908\u5909\u590a\u590b\u590c\u590d\u590e\u590f\u5910\u5911\u5912\u5913\u5914\u5915\u5916\u5917\u5918\u5919\u591a\u591b\u591c\u591d\u591e\u591f\u5920\u5921\u5922\u5923\u5924\u5925\u5926\u5927\u5928\u5929\u592a\u592b\u592c\u592d\u592e\u592f\u5930\u5931\u5932\u5933\u5934\u5935\u5936\u5937\u5938\u5939\u593a\u593b\u593c\u593d\u593e\u593f\u5940\u5941\u5942\u5943\u5944\u5945\u5946\u5947\u5948\u5949\u594a\u594b\u594c\u594d\u594e\u594f\u5950\u5951\u5952\u5953\u5954\u5955\u5956\u5957\u5958\u5959\u595a\u595b\u595c\u595d\u595e\u595f\u5960\u5961\u5962\u5963\u5964\u5965\u5966\u5967\u5968\u5969\u596a\u596b\u596c\u596d\u596e\u596f\u5970\u5971\u5972\u5973\u5974\u5975\u5976\u5977\u5978\u5979\u597a\u597b\u597c\u597d\u597e\u597f\u5980\u5981\u5982\u5983\u5984\u5985\u5986\u5987\u5988\u5989\u598a\u598b\u598c\u598d\u598e\u598f\u5990\u5991\u5992\u5993\u5994\u5995\u5996\u5997\u5998\u5999\u599a\u599b\u599c\u599d\u599e\u599f\u59a0\u59a1\u59a2\u59a3\u59a4\u59a5\u59a6\u59a7\u59a8\u59a9\u59aa\u59ab\u59ac\u59ad\u59ae\u59af\u59b0\u59b1\u59b2\u59b3\u59b4\u59b5\u59b6\u59b7\u59b8\u59b9\u59ba\u59bb\u59bc\u59bd\u59be\u59bf\u59c0\u59c1\u59c2\u59c3\u59c4\u59c5\u59c6\u59c7\u59c8\u59c9\u59ca\u59cb\u59cc\u59cd\u59ce\u59cf\u59d0\u59d1\u59d2\u59d3\u59d4\u59d5\u59d6\u59d7\u59d8\u59d9\u59da\u59db\u59dc\u59dd\u59de\u59df\u59e0\u59e1\u59e2\u59e3\u59e4\u59e5\u59e6\u59e7\u59e8\u59e9\u59ea\u59eb\u59ec\u59ed\u59ee\u59ef\u59f0\u59f1\u59f2\u59f3\u59f4\u59f5\u59f6\u59f7\u59f8\u59f9\u59fa\u59fb\u59fc\u59fd\u59fe\u59ff\u5a00\u5a01\u5a02\u5a03\u5a04\u5a05\u5a06\u5a07\u5a08\u5a09\u5a0a\u5a0b\u5a0c\u5a0d\u5a0e\u5a0f\u5a10\u5a11\u5a12\u5a13\u5a14\u5a15\u5a16\u5a17\u5a18\u5a19\u5a1a\u5a1b\u5a1c\u5a1d\u5a1e\u5a1f\u5a20\u5a21\u5a22\u5a23\u5a24\u5a25\u5a26\u5a27\u5a28\u5a29\u5a2a\u5a2b\u5a2c\u5a2d\u5a2e\u5a2f\u5a30\u5a31\u5a32\u5a33\u5a34\u5a35\u5a36\u5a37\u5a38\u5a39\u5a3a\u5a3b\u5a3c\u5a3d\u5a3e\u5a3f\u5a40\u5a41\u5a42\u5a43\u5a44\u5a45\u5a46\u5a47\u5a48\u5a49\u5a4a\u5a4b\u5a4c\u5a4d\u5a4e\u5a4f\u5a50\u5a51\u5a52\u5a53\u5a54\u5a55\u5a56\u5a57\u5a58\u5a59\u5a5a\u5a5b\u5a5c\u5a5d\u5a5e\u5a5f\u5a60\u5a61\u5a62\u5a63\u5a64\u5a65\u5a66\u5a67\u5a68\u5a69\u5a6a\u5a6b\u5a6c\u5a6d\u5a6e\u5a6f\u5a70\u5a71\u5a72\u5a73\u5a74\u5a75\u5a76\u5a77\u5a78\u5a79\u5a7a\u5a7b\u5a7c\u5a7d\u5a7e\u5a7f\u5a80\u5a81\u5a82\u5a83\u5a84\u5a85\u5a86\u5a87\u5a88\u5a89\u5a8a\u5a8b\u5a8c\u5a8d\u5a8e\u5a8f\u5a90\u5a91\u5a92\u5a93\u5a94\u5a95\u5a96\u5a97\u5a98\u5a99\u5a9a\u5a9b\u5a9c\u5a9d\u5a9e\u5a9f\u5aa0\u5aa1\u5aa2\u5aa3\u5aa4\u5aa5\u5aa6\u5aa7\u5aa8\u5aa9\u5aaa\u5aab\u5aac\u5aad\u5aae\u5aaf\u5ab0\u5ab1\u5ab2\u5ab3\u5ab4\u5ab5\u5ab6\u5ab7\u5ab8\u5ab9\u5aba\u5abb\u5abc\u5abd\u5abe\u5abf\u5ac0\u5ac1\u5ac2\u5ac3\u5ac4\u5ac5\u5ac6\u5ac7\u5ac8\u5ac9\u5aca\u5acb\u5acc\u5acd\u5ace\u5acf\u5ad0\u5ad1\u5ad2\u5ad3\u5ad4\u5ad5\u5ad6\u5ad7\u5ad8\u5ad9\u5ada\u5adb\u5adc\u5add\u5ade\u5adf\u5ae0\u5ae1\u5ae2\u5ae3\u5ae4\u5ae5\u5ae6\u5ae7\u5ae8\u5ae9\u5aea\u5aeb\u5aec\u5aed\u5aee\u5aef\u5af0\u5af1\u5af2\u5af3\u5af4\u5af5\u5af6\u5af7\u5af8\u5af9\u5afa\u5afb\u5afc\u5afd\u5afe\u5aff\u5b00\u5b01\u5b02\u5b03\u5b04\u5b05\u5b06\u5b07\u5b08\u5b09\u5b0a\u5b0b\u5b0c\u5b0d\u5b0e\u5b0f\u5b10\u5b11\u5b12\u5b13\u5b14\u5b15\u5b16\u5b17\u5b18\u5b19\u5b1a\u5b1b\u5b1c\u5b1d\u5b1e\u5b1f\u5b20\u5b21\u5b22\u5b23\u5b24\u5b25\u5b26\u5b27\u5b28\u5b29\u5b2a\u5b2b\u5b2c\u5b2d\u5b2e\u5b2f\u5b30\u5b31\u5b32\u5b33\u5b34\u5b35\u5b36\u5b37\u5b38\u5b39\u5b3a\u5b3b\u5b3c\u5b3d\u5b3e\u5b3f\u5b40\u5b41\u5b42\u5b43\u5b44\u5b45\u5b46\u5b47\u5b48\u5b49\u5b4a\u5b4b\u5b4c\u5b4d\u5b4e\u5b4f\u5b50\u5b51\u5b52\u5b53\u5b54\u5b55\u5b56\u5b57\u5b58\u5b59\u5b5a\u5b5b\u5b5c\u5b5d\u5b5e\u5b5f\u5b60\u5b61\u5b62\u5b63\u5b64\u5b65\u5b66\u5b67\u5b68\u5b69\u5b6a\u5b6b\u5b6c\u5b6d\u5b6e\u5b6f\u5b70\u5b71\u5b72\u5b73\u5b74\u5b75\u5b76\u5b77\u5b78\u5b79\u5b7a\u5b7b\u5b7c\u5b7d\u5b7e\u5b7f\u5b80\u5b81\u5b82\u5b83\u5b84\u5b85\u5b86\u5b87\u5b88\u5b89\u5b8a\u5b8b\u5b8c\u5b8d\u5b8e\u5b8f\u5b90\u5b91\u5b92\u5b93\u5b94\u5b95\u5b96\u5b97\u5b98\u5b99\u5b9a\u5b9b\u5b9c\u5b9d\u5b9e\u5b9f\u5ba0\u5ba1\u5ba2\u5ba3\u5ba4\u5ba5\u5ba6\u5ba7\u5ba8\u5ba9\u5baa\u5bab\u5bac\u5bad\u5bae\u5baf\u5bb0\u5bb1\u5bb2\u5bb3\u5bb4\u5bb5\u5bb6\u5bb7\u5bb8\u5bb9\u5bba\u5bbb\u5bbc\u5bbd\u5bbe\u5bbf\u5bc0\u5bc1\u5bc2\u5bc3\u5bc4\u5bc5\u5bc6\u5bc7\u5bc8\u5bc9\u5bca\u5bcb\u5bcc\u5bcd\u5bce\u5bcf\u5bd0\u5bd1\u5bd2\u5bd3\u5bd4\u5bd5\u5bd6\u5bd7\u5bd8\u5bd9\u5bda\u5bdb\u5bdc\u5bdd\u5bde\u5bdf\u5be0\u5be1\u5be2\u5be3\u5be4\u5be5\u5be6\u5be7\u5be8\u5be9\u5bea\u5beb\u5bec\u5bed\u5bee\u5bef\u5bf0\u5bf1\u5bf2\u5bf3\u5bf4\u5bf5\u5bf6\u5bf7\u5bf8\u5bf9\u5bfa\u5bfb\u5bfc\u5bfd\u5bfe\u5bff\u5c00\u5c01\u5c02\u5c03\u5c04\u5c05\u5c06\u5c07\u5c08\u5c09\u5c0a\u5c0b\u5c0c\u5c0d\u5c0e\u5c0f\u5c10\u5c11\u5c12\u5c13\u5c14\u5c15\u5c16\u5c17\u5c18\u5c19\u5c1a\u5c1b\u5c1c\u5c1d\u5c1e\u5c1f\u5c20\u5c21\u5c22\u5c23\u5c24\u5c25\u5c26\u5c27\u5c28\u5c29\u5c2a\u5c2b\u5c2c\u5c2d\u5c2e\u5c2f\u5c30\u5c31\u5c32\u5c33\u5c34\u5c35\u5c36\u5c37\u5c38\u5c39\u5c3a\u5c3b\u5c3c\u5c3d\u5c3e\u5c3f\u5c40\u5c41\u5c42\u5c43\u5c44\u5c45\u5c46\u5c47\u5c48\u5c49\u5c4a\u5c4b\u5c4c\u5c4d\u5c4e\u5c4f\u5c50\u5c51\u5c52\u5c53\u5c54\u5c55\u5c56\u5c57\u5c58\u5c59\u5c5a\u5c5b\u5c5c\u5c5d\u5c5e\u5c5f\u5c60\u5c61\u5c62\u5c63\u5c64\u5c65\u5c66\u5c67\u5c68\u5c69\u5c6a\u5c6b\u5c6c\u5c6d\u5c6e\u5c6f\u5c70\u5c71\u5c72\u5c73\u5c74\u5c75\u5c76\u5c77\u5c78\u5c79\u5c7a\u5c7b\u5c7c\u5c7d\u5c7e\u5c7f\u5c80\u5c81\u5c82\u5c83\u5c84\u5c85\u5c86\u5c87\u5c88\u5c89\u5c8a\u5c8b\u5c8c\u5c8d\u5c8e\u5c8f\u5c90\u5c91\u5c92\u5c93\u5c94\u5c95\u5c96\u5c97\u5c98\u5c99\u5c9a\u5c9b\u5c9c\u5c9d\u5c9e\u5c9f\u5ca0\u5ca1\u5ca2\u5ca3\u5ca4\u5ca5\u5ca6\u5ca7\u5ca8\u5ca9\u5caa\u5cab\u5cac\u5cad\u5cae\u5caf\u5cb0\u5cb1\u5cb2\u5cb3\u5cb4\u5cb5\u5cb6\u5cb7\u5cb8\u5cb9\u5cba\u5cbb\u5cbc\u5cbd\u5cbe\u5cbf\u5cc0\u5cc1\u5cc2\u5cc3\u5cc4\u5cc5\u5cc6\u5cc7\u5cc8\u5cc9\u5cca\u5ccb\u5ccc\u5ccd\u5cce\u5ccf\u5cd0\u5cd1\u5cd2\u5cd3\u5cd4\u5cd5\u5cd6\u5cd7\u5cd8\u5cd9\u5cda\u5cdb\u5cdc\u5cdd\u5cde\u5cdf\u5ce0\u5ce1\u5ce2\u5ce3\u5ce4\u5ce5\u5ce6\u5ce7\u5ce8\u5ce9\u5cea\u5ceb\u5cec\u5ced\u5cee\u5cef\u5cf0\u5cf1\u5cf2\u5cf3\u5cf4\u5cf5\u5cf6\u5cf7\u5cf8\u5cf9\u5cfa\u5cfb\u5cfc\u5cfd\u5cfe\u5cff\u5d00\u5d01\u5d02\u5d03\u5d04\u5d05\u5d06\u5d07\u5d08\u5d09\u5d0a\u5d0b\u5d0c\u5d0d\u5d0e\u5d0f\u5d10\u5d11\u5d12\u5d13\u5d14\u5d15\u5d16\u5d17\u5d18\u5d19\u5d1a\u5d1b\u5d1c\u5d1d\u5d1e\u5d1f\u5d20\u5d21\u5d22\u5d23\u5d24\u5d25\u5d26\u5d27\u5d28\u5d29\u5d2a\u5d2b\u5d2c\u5d2d\u5d2e\u5d2f\u5d30\u5d31\u5d32\u5d33\u5d34\u5d35\u5d36\u5d37\u5d38\u5d39\u5d3a\u5d3b\u5d3c\u5d3d\u5d3e\u5d3f\u5d40\u5d41\u5d42\u5d43\u5d44\u5d45\u5d46\u5d47\u5d48\u5d49\u5d4a\u5d4b\u5d4c\u5d4d\u5d4e\u5d4f\u5d50\u5d51\u5d52\u5d53\u5d54\u5d55\u5d56\u5d57\u5d58\u5d59\u5d5a\u5d5b\u5d5c\u5d5d\u5d5e\u5d5f\u5d60\u5d61\u5d62\u5d63\u5d64\u5d65\u5d66\u5d67\u5d68\u5d69\u5d6a\u5d6b\u5d6c\u5d6d\u5d6e\u5d6f\u5d70\u5d71\u5d72\u5d73\u5d74\u5d75\u5d76\u5d77\u5d78\u5d79\u5d7a\u5d7b\u5d7c\u5d7d\u5d7e\u5d7f\u5d80\u5d81\u5d82\u5d83\u5d84\u5d85\u5d86\u5d87\u5d88\u5d89\u5d8a\u5d8b\u5d8c\u5d8d\u5d8e\u5d8f\u5d90\u5d91\u5d92\u5d93\u5d94\u5d95\u5d96\u5d97\u5d98\u5d99\u5d9a\u5d9b\u5d9c\u5d9d\u5d9e\u5d9f\u5da0\u5da1\u5da2\u5da3\u5da4\u5da5\u5da6\u5da7\u5da8\u5da9\u5daa\u5dab\u5dac\u5dad\u5dae\u5daf\u5db0\u5db1\u5db2\u5db3\u5db4\u5db5\u5db6\u5db7\u5db8\u5db9\u5dba\u5dbb\u5dbc\u5dbd\u5dbe\u5dbf\u5dc0\u5dc1\u5dc2\u5dc3\u5dc4\u5dc5\u5dc6\u5dc7\u5dc8\u5dc9\u5dca\u5dcb\u5dcc\u5dcd\u5dce\u5dcf\u5dd0\u5dd1\u5dd2\u5dd3\u5dd4\u5dd5\u5dd6\u5dd7\u5dd8\u5dd9\u5dda\u5ddb\u5ddc\u5ddd\u5dde\u5ddf\u5de0\u5de1\u5de2\u5de3\u5de4\u5de5\u5de6\u5de7\u5de8\u5de9\u5dea\u5deb\u5dec\u5ded\u5dee\u5def\u5df0\u5df1\u5df2\u5df3\u5df4\u5df5\u5df6\u5df7\u5df8\u5df9\u5dfa\u5dfb\u5dfc\u5dfd\u5dfe\u5dff\u5e00\u5e01\u5e02\u5e03\u5e04\u5e05\u5e06\u5e07\u5e08\u5e09\u5e0a\u5e0b\u5e0c\u5e0d\u5e0e\u5e0f\u5e10\u5e11\u5e12\u5e13\u5e14\u5e15\u5e16\u5e17\u5e18\u5e19\u5e1a\u5e1b\u5e1c\u5e1d\u5e1e\u5e1f\u5e20\u5e21\u5e22\u5e23\u5e24\u5e25\u5e26\u5e27\u5e28\u5e29\u5e2a\u5e2b\u5e2c\u5e2d\u5e2e\u5e2f\u5e30\u5e31\u5e32\u5e33\u5e34\u5e35\u5e36\u5e37\u5e38\u5e39\u5e3a\u5e3b\u5e3c\u5e3d\u5e3e\u5e3f\u5e40\u5e41\u5e42\u5e43\u5e44\u5e45\u5e46\u5e47\u5e48\u5e49\u5e4a\u5e4b\u5e4c\u5e4d\u5e4e\u5e4f\u5e50\u5e51\u5e52\u5e53\u5e54\u5e55\u5e56\u5e57\u5e58\u5e59\u5e5a\u5e5b\u5e5c\u5e5d\u5e5e\u5e5f\u5e60\u5e61\u5e62\u5e63\u5e64\u5e65\u5e66\u5e67\u5e68\u5e69\u5e6a\u5e6b\u5e6c\u5e6d\u5e6e\u5e6f\u5e70\u5e71\u5e72\u5e73\u5e74\u5e75\u5e76\u5e77\u5e78\u5e79\u5e7a\u5e7b\u5e7c\u5e7d\u5e7e\u5e7f\u5e80\u5e81\u5e82\u5e83\u5e84\u5e85\u5e86\u5e87\u5e88\u5e89\u5e8a\u5e8b\u5e8c\u5e8d\u5e8e\u5e8f\u5e90\u5e91\u5e92\u5e93\u5e94\u5e95\u5e96\u5e97\u5e98\u5e99\u5e9a\u5e9b\u5e9c\u5e9d\u5e9e\u5e9f\u5ea0\u5ea1\u5ea2\u5ea3\u5ea4\u5ea5\u5ea6\u5ea7\u5ea8\u5ea9\u5eaa\u5eab\u5eac\u5ead\u5eae\u5eaf\u5eb0\u5eb1\u5eb2\u5eb3\u5eb4\u5eb5\u5eb6\u5eb7\u5eb8\u5eb9\u5eba\u5ebb\u5ebc\u5ebd\u5ebe\u5ebf\u5ec0\u5ec1\u5ec2\u5ec3\u5ec4\u5ec5\u5ec6\u5ec7\u5ec8\u5ec9\u5eca\u5ecb\u5ecc\u5ecd\u5ece\u5ecf\u5ed0\u5ed1\u5ed2\u5ed3\u5ed4\u5ed5\u5ed6\u5ed7\u5ed8\u5ed9\u5eda\u5edb\u5edc\u5edd\u5ede\u5edf\u5ee0\u5ee1\u5ee2\u5ee3\u5ee4\u5ee5\u5ee6\u5ee7\u5ee8\u5ee9\u5eea\u5eeb\u5eec\u5eed\u5eee\u5eef\u5ef0\u5ef1\u5ef2\u5ef3\u5ef4\u5ef5\u5ef6\u5ef7\u5ef8\u5ef9\u5efa\u5efb\u5efc\u5efd\u5efe\u5eff\u5f00\u5f01\u5f02\u5f03\u5f04\u5f05\u5f06\u5f07\u5f08\u5f09\u5f0a\u5f0b\u5f0c\u5f0d\u5f0e\u5f0f\u5f10\u5f11\u5f12\u5f13\u5f14\u5f15\u5f16\u5f17\u5f18\u5f19\u5f1a\u5f1b\u5f1c\u5f1d\u5f1e\u5f1f\u5f20\u5f21\u5f22\u5f23\u5f24\u5f25\u5f26\u5f27\u5f28\u5f29\u5f2a\u5f2b\u5f2c\u5f2d\u5f2e\u5f2f\u5f30\u5f31\u5f32\u5f33\u5f34\u5f35\u5f36\u5f37\u5f38\u5f39\u5f3a\u5f3b\u5f3c\u5f3d\u5f3e\u5f3f\u5f40\u5f41\u5f42\u5f43\u5f44\u5f45\u5f46\u5f47\u5f48\u5f49\u5f4a\u5f4b\u5f4c\u5f4d\u5f4e\u5f4f\u5f50\u5f51\u5f52\u5f53\u5f54\u5f55\u5f56\u5f57\u5f58\u5f59\u5f5a\u5f5b\u5f5c\u5f5d\u5f5e\u5f5f\u5f60\u5f61\u5f62\u5f63\u5f64\u5f65\u5f66\u5f67\u5f68\u5f69\u5f6a\u5f6b\u5f6c\u5f6d\u5f6e\u5f6f\u5f70\u5f71\u5f72\u5f73\u5f74\u5f75\u5f76\u5f77\u5f78\u5f79\u5f7a\u5f7b\u5f7c\u5f7d\u5f7e\u5f7f\u5f80\u5f81\u5f82\u5f83\u5f84\u5f85\u5f86\u5f87\u5f88\u5f89\u5f8a\u5f8b\u5f8c\u5f8d\u5f8e\u5f8f\u5f90\u5f91\u5f92\u5f93\u5f94\u5f95\u5f96\u5f97\u5f98\u5f99\u5f9a\u5f9b\u5f9c\u5f9d\u5f9e\u5f9f\u5fa0\u5fa1\u5fa2\u5fa3\u5fa4\u5fa5\u5fa6\u5fa7\u5fa8\u5fa9\u5faa\u5fab\u5fac\u5fad\u5fae\u5faf\u5fb0\u5fb1\u5fb2\u5fb3\u5fb4\u5fb5\u5fb6\u5fb7\u5fb8\u5fb9\u5fba\u5fbb\u5fbc\u5fbd\u5fbe\u5fbf\u5fc0\u5fc1\u5fc2\u5fc3\u5fc4\u5fc5\u5fc6\u5fc7\u5fc8\u5fc9\u5fca\u5fcb\u5fcc\u5fcd\u5fce\u5fcf\u5fd0\u5fd1\u5fd2\u5fd3\u5fd4\u5fd5\u5fd6\u5fd7\u5fd8\u5fd9\u5fda\u5fdb\u5fdc\u5fdd\u5fde\u5fdf\u5fe0\u5fe1\u5fe2\u5fe3\u5fe4\u5fe5\u5fe6\u5fe7\u5fe8\u5fe9\u5fea\u5feb\u5fec\u5fed\u5fee\u5fef\u5ff0\u5ff1\u5ff2\u5ff3\u5ff4\u5ff5\u5ff6\u5ff7\u5ff8\u5ff9\u5ffa\u5ffb\u5ffc\u5ffd\u5ffe\u5fff\u6000\u6001\u6002\u6003\u6004\u6005\u6006\u6007\u6008\u6009\u600a\u600b\u600c\u600d\u600e\u600f\u6010\u6011\u6012\u6013\u6014\u6015\u6016\u6017\u6018\u6019\u601a\u601b\u601c\u601d\u601e\u601f\u6020\u6021\u6022\u6023\u6024\u6025\u6026\u6027\u6028\u6029\u602a\u602b\u602c\u602d\u602e\u602f\u6030\u6031\u6032\u6033\u6034\u6035\u6036\u6037\u6038\u6039\u603a\u603b\u603c\u603d\u603e\u603f\u6040\u6041\u6042\u6043\u6044\u6045\u6046\u6047\u6048\u6049\u604a\u604b\u604c\u604d\u604e\u604f\u6050\u6051\u6052\u6053\u6054\u6055\u6056\u6057\u6058\u6059\u605a\u605b\u605c\u605d\u605e\u605f\u6060\u6061\u6062\u6063\u6064\u6065\u6066\u6067\u6068\u6069\u606a\u606b\u606c\u606d\u606e\u606f\u6070\u6071\u6072\u6073\u6074\u6075\u6076\u6077\u6078\u6079\u607a\u607b\u607c\u607d\u607e\u607f\u6080\u6081\u6082\u6083\u6084\u6085\u6086\u6087\u6088\u6089\u608a\u608b\u608c\u608d\u608e\u608f\u6090\u6091\u6092\u6093\u6094\u6095\u6096\u6097\u6098\u6099\u609a\u609b\u609c\u609d\u609e\u609f\u60a0\u60a1\u60a2\u60a3\u60a4\u60a5\u60a6\u60a7\u60a8\u60a9\u60aa\u60ab\u60ac\u60ad\u60ae\u60af\u60b0\u60b1\u60b2\u60b3\u60b4\u60b5\u60b6\u60b7\u60b8\u60b9\u60ba\u60bb\u60bc\u60bd\u60be\u60bf\u60c0\u60c1\u60c2\u60c3\u60c4\u60c5\u60c6\u60c7\u60c8\u60c9\u60ca\u60cb\u60cc\u60cd\u60ce\u60cf\u60d0\u60d1\u60d2\u60d3\u60d4\u60d5\u60d6\u60d7\u60d8\u60d9\u60da\u60db\u60dc\u60dd\u60de\u60df\u60e0\u60e1\u60e2\u60e3\u60e4\u60e5\u60e6\u60e7\u60e8\u60e9\u60ea\u60eb\u60ec\u60ed\u60ee\u60ef\u60f0\u60f1\u60f2\u60f3\u60f4\u60f5\u60f6\u60f7\u60f8\u60f9\u60fa\u60fb\u60fc\u60fd\u60fe\u60ff\u6100\u6101\u6102\u6103\u6104\u6105\u6106\u6107\u6108\u6109\u610a\u610b\u610c\u610d\u610e\u610f\u6110\u6111\u6112\u6113\u6114\u6115\u6116\u6117\u6118\u6119\u611a\u611b\u611c\u611d\u611e\u611f\u6120\u6121\u6122\u6123\u6124\u6125\u6126\u6127\u6128\u6129\u612a\u612b\u612c\u612d\u612e\u612f\u6130\u6131\u6132\u6133\u6134\u6135\u6136\u6137\u6138\u6139\u613a\u613b\u613c\u613d\u613e\u613f\u6140\u6141\u6142\u6143\u6144\u6145\u6146\u6147\u6148\u6149\u614a\u614b\u614c\u614d\u614e\u614f\u6150\u6151\u6152\u6153\u6154\u6155\u6156\u6157\u6158\u6159\u615a\u615b\u615c\u615d\u615e\u615f\u6160\u6161\u6162\u6163\u6164\u6165\u6166\u6167\u6168\u6169\u616a\u616b\u616c\u616d\u616e\u616f\u6170\u6171\u6172\u6173\u6174\u6175\u6176\u6177\u6178\u6179\u617a\u617b\u617c\u617d\u617e\u617f\u6180\u6181\u6182\u6183\u6184\u6185\u6186\u6187\u6188\u6189\u618a\u618b\u618c\u618d\u618e\u618f\u6190\u6191\u6192\u6193\u6194\u6195\u6196\u6197\u6198\u6199\u619a\u619b\u619c\u619d\u619e\u619f\u61a0\u61a1\u61a2\u61a3\u61a4\u61a5\u61a6\u61a7\u61a8\u61a9\u61aa\u61ab\u61ac\u61ad\u61ae\u61af\u61b0\u61b1\u61b2\u61b3\u61b4\u61b5\u61b6\u61b7\u61b8\u61b9\u61ba\u61bb\u61bc\u61bd\u61be\u61bf\u61c0\u61c1\u61c2\u61c3\u61c4\u61c5\u61c6\u61c7\u61c8\u61c9\u61ca\u61cb\u61cc\u61cd\u61ce\u61cf\u61d0\u61d1\u61d2\u61d3\u61d4\u61d5\u61d6\u61d7\u61d8\u61d9\u61da\u61db\u61dc\u61dd\u61de\u61df\u61e0\u61e1\u61e2\u61e3\u61e4\u61e5\u61e6\u61e7\u61e8\u61e9\u61ea\u61eb\u61ec\u61ed\u61ee\u61ef\u61f0\u61f1\u61f2\u61f3\u61f4\u61f5\u61f6\u61f7\u61f8\u61f9\u61fa\u61fb\u61fc\u61fd\u61fe\u61ff\u6200\u6201\u6202\u6203\u6204\u6205\u6206\u6207\u6208\u6209\u620a\u620b\u620c\u620d\u620e\u620f\u6210\u6211\u6212\u6213\u6214\u6215\u6216\u6217\u6218\u6219\u621a\u621b\u621c\u621d\u621e\u621f\u6220\u6221\u6222\u6223\u6224\u6225\u6226\u6227\u6228\u6229\u622a\u622b\u622c\u622d\u622e\u622f\u6230\u6231\u6232\u6233\u6234\u6235\u6236\u6237\u6238\u6239\u623a\u623b\u623c\u623d\u623e\u623f\u6240\u6241\u6242\u6243\u6244\u6245\u6246\u6247\u6248\u6249\u624a\u624b\u624c\u624d\u624e\u624f\u6250\u6251\u6252\u6253\u6254\u6255\u6256\u6257\u6258\u6259\u625a\u625b\u625c\u625d\u625e\u625f\u6260\u6261\u6262\u6263\u6264\u6265\u6266\u6267\u6268\u6269\u626a\u626b\u626c\u626d\u626e\u626f\u6270\u6271\u6272\u6273\u6274\u6275\u6276\u6277\u6278\u6279\u627a\u627b\u627c\u627d\u627e\u627f\u6280\u6281\u6282\u6283\u6284\u6285\u6286\u6287\u6288\u6289\u628a\u628b\u628c\u628d\u628e\u628f\u6290\u6291\u6292\u6293\u6294\u6295\u6296\u6297\u6298\u6299\u629a\u629b\u629c\u629d\u629e\u629f\u62a0\u62a1\u62a2\u62a3\u62a4\u62a5\u62a6\u62a7\u62a8\u62a9\u62aa\u62ab\u62ac\u62ad\u62ae\u62af\u62b0\u62b1\u62b2\u62b3\u62b4\u62b5\u62b6\u62b7\u62b8\u62b9\u62ba\u62bb\u62bc\u62bd\u62be\u62bf\u62c0\u62c1\u62c2\u62c3\u62c4\u62c5\u62c6\u62c7\u62c8\u62c9\u62ca\u62cb\u62cc\u62cd\u62ce\u62cf\u62d0\u62d1\u62d2\u62d3\u62d4\u62d5\u62d6\u62d7\u62d8\u62d9\u62da\u62db\u62dc\u62dd\u62de\u62df\u62e0\u62e1\u62e2\u62e3\u62e4\u62e5\u62e6\u62e7\u62e8\u62e9\u62ea\u62eb\u62ec\u62ed\u62ee\u62ef\u62f0\u62f1\u62f2\u62f3\u62f4\u62f5\u62f6\u62f7\u62f8\u62f9\u62fa\u62fb\u62fc\u62fd\u62fe\u62ff\u6300\u6301\u6302\u6303\u6304\u6305\u6306\u6307\u6308\u6309\u630a\u630b\u630c\u630d\u630e\u630f\u6310\u6311\u6312\u6313\u6314\u6315\u6316\u6317\u6318\u6319\u631a\u631b\u631c\u631d\u631e\u631f\u6320\u6321\u6322\u6323\u6324\u6325\u6326\u6327\u6328\u6329\u632a\u632b\u632c\u632d\u632e\u632f\u6330\u6331\u6332\u6333\u6334\u6335\u6336\u6337\u6338\u6339\u633a\u633b\u633c\u633d\u633e\u633f\u6340\u6341\u6342\u6343\u6344\u6345\u6346\u6347\u6348\u6349\u634a\u634b\u634c\u634d\u634e\u634f\u6350\u6351\u6352\u6353\u6354\u6355\u6356\u6357\u6358\u6359\u635a\u635b\u635c\u635d\u635e\u635f\u6360\u6361\u6362\u6363\u6364\u6365\u6366\u6367\u6368\u6369\u636a\u636b\u636c\u636d\u636e\u636f\u6370\u6371\u6372\u6373\u6374\u6375\u6376\u6377\u6378\u6379\u637a\u637b\u637c\u637d\u637e\u637f\u6380\u6381\u6382\u6383\u6384\u6385\u6386\u6387\u6388\u6389\u638a\u638b\u638c\u638d\u638e\u638f\u6390\u6391\u6392\u6393\u6394\u6395\u6396\u6397\u6398\u6399\u639a\u639b\u639c\u639d\u639e\u639f\u63a0\u63a1\u63a2\u63a3\u63a4\u63a5\u63a6\u63a7\u63a8\u63a9\u63aa\u63ab\u63ac\u63ad\u63ae\u63af\u63b0\u63b1\u63b2\u63b3\u63b4\u63b5\u63b6\u63b7\u63b8\u63b9\u63ba\u63bb\u63bc\u63bd\u63be\u63bf\u63c0\u63c1\u63c2\u63c3\u63c4\u63c5\u63c6\u63c7\u63c8\u63c9\u63ca\u63cb\u63cc\u63cd\u63ce\u63cf\u63d0\u63d1\u63d2\u63d3\u63d4\u63d5\u63d6\u63d7\u63d8\u63d9\u63da\u63db\u63dc\u63dd\u63de\u63df\u63e0\u63e1\u63e2\u63e3\u63e4\u63e5\u63e6\u63e7\u63e8\u63e9\u63ea\u63eb\u63ec\u63ed\u63ee\u63ef\u63f0\u63f1\u63f2\u63f3\u63f4\u63f5\u63f6\u63f7\u63f8\u63f9\u63fa\u63fb\u63fc\u63fd\u63fe\u63ff\u6400\u6401\u6402\u6403\u6404\u6405\u6406\u6407\u6408\u6409\u640a\u640b\u640c\u640d\u640e\u640f\u6410\u6411\u6412\u6413\u6414\u6415\u6416\u6417\u6418\u6419\u641a\u641b\u641c\u641d\u641e\u641f\u6420\u6421\u6422\u6423\u6424\u6425\u6426\u6427\u6428\u6429\u642a\u642b\u642c\u642d\u642e\u642f\u6430\u6431\u6432\u6433\u6434\u6435\u6436\u6437\u6438\u6439\u643a\u643b\u643c\u643d\u643e\u643f\u6440\u6441\u6442\u6443\u6444\u6445\u6446\u6447\u6448\u6449\u644a\u644b\u644c\u644d\u644e\u644f\u6450\u6451\u6452\u6453\u6454\u6455\u6456\u6457\u6458\u6459\u645a\u645b\u645c\u645d\u645e\u645f\u6460\u6461\u6462\u6463\u6464\u6465\u6466\u6467\u6468\u6469\u646a\u646b\u646c\u646d\u646e\u646f\u6470\u6471\u6472\u6473\u6474\u6475\u6476\u6477\u6478\u6479\u647a\u647b\u647c\u647d\u647e\u647f\u6480\u6481\u6482\u6483\u6484\u6485\u6486\u6487\u6488\u6489\u648a\u648b\u648c\u648d\u648e\u648f\u6490\u6491\u6492\u6493\u6494\u6495\u6496\u6497\u6498\u6499\u649a\u649b\u649c\u649d\u649e\u649f\u64a0\u64a1\u64a2\u64a3\u64a4\u64a5\u64a6\u64a7\u64a8\u64a9\u64aa\u64ab\u64ac\u64ad\u64ae\u64af\u64b0\u64b1\u64b2\u64b3\u64b4\u64b5\u64b6\u64b7\u64b8\u64b9\u64ba\u64bb\u64bc\u64bd\u64be\u64bf\u64c0\u64c1\u64c2\u64c3\u64c4\u64c5\u64c6\u64c7\u64c8\u64c9\u64ca\u64cb\u64cc\u64cd\u64ce\u64cf\u64d0\u64d1\u64d2\u64d3\u64d4\u64d5\u64d6\u64d7\u64d8\u64d9\u64da\u64db\u64dc\u64dd\u64de\u64df\u64e0\u64e1\u64e2\u64e3\u64e4\u64e5\u64e6\u64e7\u64e8\u64e9\u64ea\u64eb\u64ec\u64ed\u64ee\u64ef\u64f0\u64f1\u64f2\u64f3\u64f4\u64f5\u64f6\u64f7\u64f8\u64f9\u64fa\u64fb\u64fc\u64fd\u64fe\u64ff\u6500\u6501\u6502\u6503\u6504\u6505\u6506\u6507\u6508\u6509\u650a\u650b\u650c\u650d\u650e\u650f\u6510\u6511\u6512\u6513\u6514\u6515\u6516\u6517\u6518\u6519\u651a\u651b\u651c\u651d\u651e\u651f\u6520\u6521\u6522\u6523\u6524\u6525\u6526\u6527\u6528\u6529\u652a\u652b\u652c\u652d\u652e\u652f\u6530\u6531\u6532\u6533\u6534\u6535\u6536\u6537\u6538\u6539\u653a\u653b\u653c\u653d\u653e\u653f\u6540\u6541\u6542\u6543\u6544\u6545\u6546\u6547\u6548\u6549\u654a\u654b\u654c\u654d\u654e\u654f\u6550\u6551\u6552\u6553\u6554\u6555\u6556\u6557\u6558\u6559\u655a\u655b\u655c\u655d\u655e\u655f\u6560\u6561\u6562\u6563\u6564\u6565\u6566\u6567\u6568\u6569\u656a\u656b\u656c\u656d\u656e\u656f\u6570\u6571\u6572\u6573\u6574\u6575\u6576\u6577\u6578\u6579\u657a\u657b\u657c\u657d\u657e\u657f\u6580\u6581\u6582\u6583\u6584\u6585\u6586\u6587\u6588\u6589\u658a\u658b\u658c\u658d\u658e\u658f\u6590\u6591\u6592\u6593\u6594\u6595\u6596\u6597\u6598\u6599\u659a\u659b\u659c\u659d\u659e\u659f\u65a0\u65a1\u65a2\u65a3\u65a4\u65a5\u65a6\u65a7\u65a8\u65a9\u65aa\u65ab\u65ac\u65ad\u65ae\u65af\u65b0\u65b1\u65b2\u65b3\u65b4\u65b5\u65b6\u65b7\u65b8\u65b9\u65ba\u65bb\u65bc\u65bd\u65be\u65bf\u65c0\u65c1\u65c2\u65c3\u65c4\u65c5\u65c6\u65c7\u65c8\u65c9\u65ca\u65cb\u65cc\u65cd\u65ce\u65cf\u65d0\u65d1\u65d2\u65d3\u65d4\u65d5\u65d6\u65d7\u65d8\u65d9\u65da\u65db\u65dc\u65dd\u65de\u65df\u65e0\u65e1\u65e2\u65e3\u65e4\u65e5\u65e6\u65e7\u65e8\u65e9\u65ea\u65eb\u65ec\u65ed\u65ee\u65ef\u65f0\u65f1\u65f2\u65f3\u65f4\u65f5\u65f6\u65f7\u65f8\u65f9\u65fa\u65fb\u65fc\u65fd\u65fe\u65ff\u6600\u6601\u6602\u6603\u6604\u6605\u6606\u6607\u6608\u6609\u660a\u660b\u660c\u660d\u660e\u660f\u6610\u6611\u6612\u6613\u6614\u6615\u6616\u6617\u6618\u6619\u661a\u661b\u661c\u661d\u661e\u661f\u6620\u6621\u6622\u6623\u6624\u6625\u6626\u6627\u6628\u6629\u662a\u662b\u662c\u662d\u662e\u662f\u6630\u6631\u6632\u6633\u6634\u6635\u6636\u6637\u6638\u6639\u663a\u663b\u663c\u663d\u663e\u663f\u6640\u6641\u6642\u6643\u6644\u6645\u6646\u6647\u6648\u6649\u664a\u664b\u664c\u664d\u664e\u664f\u6650\u6651\u6652\u6653\u6654\u6655\u6656\u6657\u6658\u6659\u665a\u665b\u665c\u665d\u665e\u665f\u6660\u6661\u6662\u6663\u6664\u6665\u6666\u6667\u6668\u6669\u666a\u666b\u666c\u666d\u666e\u666f\u6670\u6671\u6672\u6673\u6674\u6675\u6676\u6677\u6678\u6679\u667a\u667b\u667c\u667d\u667e\u667f\u6680\u6681\u6682\u6683\u6684\u6685\u6686\u6687\u6688\u6689\u668a\u668b\u668c\u668d\u668e\u668f\u6690\u6691\u6692\u6693\u6694\u6695\u6696\u6697\u6698\u6699\u669a\u669b\u669c\u669d\u669e\u669f\u66a0\u66a1\u66a2\u66a3\u66a4\u66a5\u66a6\u66a7\u66a8\u66a9\u66aa\u66ab\u66ac\u66ad\u66ae\u66af\u66b0\u66b1\u66b2\u66b3\u66b4\u66b5\u66b6\u66b7\u66b8\u66b9\u66ba\u66bb\u66bc\u66bd\u66be\u66bf\u66c0\u66c1\u66c2\u66c3\u66c4\u66c5\u66c6\u66c7\u66c8\u66c9\u66ca\u66cb\u66cc\u66cd\u66ce\u66cf\u66d0\u66d1\u66d2\u66d3\u66d4\u66d5\u66d6\u66d7\u66d8\u66d9\u66da\u66db\u66dc\u66dd\u66de\u66df\u66e0\u66e1\u66e2\u66e3\u66e4\u66e5\u66e6\u66e7\u66e8\u66e9\u66ea\u66eb\u66ec\u66ed\u66ee\u66ef\u66f0\u66f1\u66f2\u66f3\u66f4\u66f5\u66f6\u66f7\u66f8\u66f9\u66fa\u66fb\u66fc\u66fd\u66fe\u66ff\u6700\u6701\u6702\u6703\u6704\u6705\u6706\u6707\u6708\u6709\u670a\u670b\u670c\u670d\u670e\u670f\u6710\u6711\u6712\u6713\u6714\u6715\u6716\u6717\u6718\u6719\u671a\u671b\u671c\u671d\u671e\u671f\u6720\u6721\u6722\u6723\u6724\u6725\u6726\u6727\u6728\u6729\u672a\u672b\u672c\u672d\u672e\u672f\u6730\u6731\u6732\u6733\u6734\u6735\u6736\u6737\u6738\u6739\u673a\u673b\u673c\u673d\u673e\u673f\u6740\u6741\u6742\u6743\u6744\u6745\u6746\u6747\u6748\u6749\u674a\u674b\u674c\u674d\u674e\u674f\u6750\u6751\u6752\u6753\u6754\u6755\u6756\u6757\u6758\u6759\u675a\u675b\u675c\u675d\u675e\u675f\u6760\u6761\u6762\u6763\u6764\u6765\u6766\u6767\u6768\u6769\u676a\u676b\u676c\u676d\u676e\u676f\u6770\u6771\u6772\u6773\u6774\u6775\u6776\u6777\u6778\u6779\u677a\u677b\u677c\u677d\u677e\u677f\u6780\u6781\u6782\u6783\u6784\u6785\u6786\u6787\u6788\u6789\u678a\u678b\u678c\u678d\u678e\u678f\u6790\u6791\u6792\u6793\u6794\u6795\u6796\u6797\u6798\u6799\u679a\u679b\u679c\u679d\u679e\u679f\u67a0\u67a1\u67a2\u67a3\u67a4\u67a5\u67a6\u67a7\u67a8\u67a9\u67aa\u67ab\u67ac\u67ad\u67ae\u67af\u67b0\u67b1\u67b2\u67b3\u67b4\u67b5\u67b6\u67b7\u67b8\u67b9\u67ba\u67bb\u67bc\u67bd\u67be\u67bf\u67c0\u67c1\u67c2\u67c3\u67c4\u67c5\u67c6\u67c7\u67c8\u67c9\u67ca\u67cb\u67cc\u67cd\u67ce\u67cf\u67d0\u67d1\u67d2\u67d3\u67d4\u67d5\u67d6\u67d7\u67d8\u67d9\u67da\u67db\u67dc\u67dd\u67de\u67df\u67e0\u67e1\u67e2\u67e3\u67e4\u67e5\u67e6\u67e7\u67e8\u67e9\u67ea\u67eb\u67ec\u67ed\u67ee\u67ef\u67f0\u67f1\u67f2\u67f3\u67f4\u67f5\u67f6\u67f7\u67f8\u67f9\u67fa\u67fb\u67fc\u67fd\u67fe\u67ff\u6800\u6801\u6802\u6803\u6804\u6805\u6806\u6807\u6808\u6809\u680a\u680b\u680c\u680d\u680e\u680f\u6810\u6811\u6812\u6813\u6814\u6815\u6816\u6817\u6818\u6819\u681a\u681b\u681c\u681d\u681e\u681f\u6820\u6821\u6822\u6823\u6824\u6825\u6826\u6827\u6828\u6829\u682a\u682b\u682c\u682d\u682e\u682f\u6830\u6831\u6832\u6833\u6834\u6835\u6836\u6837\u6838\u6839\u683a\u683b\u683c\u683d\u683e\u683f\u6840\u6841\u6842\u6843\u6844\u6845\u6846\u6847\u6848\u6849\u684a\u684b\u684c\u684d\u684e\u684f\u6850\u6851\u6852\u6853\u6854\u6855\u6856\u6857\u6858\u6859\u685a\u685b\u685c\u685d\u685e\u685f\u6860\u6861\u6862\u6863\u6864\u6865\u6866\u6867\u6868\u6869\u686a\u686b\u686c\u686d\u686e\u686f\u6870\u6871\u6872\u6873\u6874\u6875\u6876\u6877\u6878\u6879\u687a\u687b\u687c\u687d\u687e\u687f\u6880\u6881\u6882\u6883\u6884\u6885\u6886\u6887\u6888\u6889\u688a\u688b\u688c\u688d\u688e\u688f\u6890\u6891\u6892\u6893\u6894\u6895\u6896\u6897\u6898\u6899\u689a\u689b\u689c\u689d\u689e\u689f\u68a0\u68a1\u68a2\u68a3\u68a4\u68a5\u68a6\u68a7\u68a8\u68a9\u68aa\u68ab\u68ac\u68ad\u68ae\u68af\u68b0\u68b1\u68b2\u68b3\u68b4\u68b5\u68b6\u68b7\u68b8\u68b9\u68ba\u68bb\u68bc\u68bd\u68be\u68bf\u68c0\u68c1\u68c2\u68c3\u68c4\u68c5\u68c6\u68c7\u68c8\u68c9\u68ca\u68cb\u68cc\u68cd\u68ce\u68cf\u68d0\u68d1\u68d2\u68d3\u68d4\u68d5\u68d6\u68d7\u68d8\u68d9\u68da\u68db\u68dc\u68dd\u68de\u68df\u68e0\u68e1\u68e2\u68e3\u68e4\u68e5\u68e6\u68e7\u68e8\u68e9\u68ea\u68eb\u68ec\u68ed\u68ee\u68ef\u68f0\u68f1\u68f2\u68f3\u68f4\u68f5\u68f6\u68f7\u68f8\u68f9\u68fa\u68fb\u68fc\u68fd\u68fe\u68ff\u6900\u6901\u6902\u6903\u6904\u6905\u6906\u6907\u6908\u6909\u690a\u690b\u690c\u690d\u690e\u690f\u6910\u6911\u6912\u6913\u6914\u6915\u6916\u6917\u6918\u6919\u691a\u691b\u691c\u691d\u691e\u691f\u6920\u6921\u6922\u6923\u6924\u6925\u6926\u6927\u6928\u6929\u692a\u692b\u692c\u692d\u692e\u692f\u6930\u6931\u6932\u6933\u6934\u6935\u6936\u6937\u6938\u6939\u693a\u693b\u693c\u693d\u693e\u693f\u6940\u6941\u6942\u6943\u6944\u6945\u6946\u6947\u6948\u6949\u694a\u694b\u694c\u694d\u694e\u694f\u6950\u6951\u6952\u6953\u6954\u6955\u6956\u6957\u6958\u6959\u695a\u695b\u695c\u695d\u695e\u695f\u6960\u6961\u6962\u6963\u6964\u6965\u6966\u6967\u6968\u6969\u696a\u696b\u696c\u696d\u696e\u696f\u6970\u6971\u6972\u6973\u6974\u6975\u6976\u6977\u6978\u6979\u697a\u697b\u697c\u697d\u697e\u697f\u6980\u6981\u6982\u6983\u6984\u6985\u6986\u6987\u6988\u6989\u698a\u698b\u698c\u698d\u698e\u698f\u6990\u6991\u6992\u6993\u6994\u6995\u6996\u6997\u6998\u6999\u699a\u699b\u699c\u699d\u699e\u699f\u69a0\u69a1\u69a2\u69a3\u69a4\u69a5\u69a6\u69a7\u69a8\u69a9\u69aa\u69ab\u69ac\u69ad\u69ae\u69af\u69b0\u69b1\u69b2\u69b3\u69b4\u69b5\u69b6\u69b7\u69b8\u69b9\u69ba\u69bb\u69bc\u69bd\u69be\u69bf\u69c0\u69c1\u69c2\u69c3\u69c4\u69c5\u69c6\u69c7\u69c8\u69c9\u69ca\u69cb\u69cc\u69cd\u69ce\u69cf\u69d0\u69d1\u69d2\u69d3\u69d4\u69d5\u69d6\u69d7\u69d8\u69d9\u69da\u69db\u69dc\u69dd\u69de\u69df\u69e0\u69e1\u69e2\u69e3\u69e4\u69e5\u69e6\u69e7\u69e8\u69e9\u69ea\u69eb\u69ec\u69ed\u69ee\u69ef\u69f0\u69f1\u69f2\u69f3\u69f4\u69f5\u69f6\u69f7\u69f8\u69f9\u69fa\u69fb\u69fc\u69fd\u69fe\u69ff\u6a00\u6a01\u6a02\u6a03\u6a04\u6a05\u6a06\u6a07\u6a08\u6a09\u6a0a\u6a0b\u6a0c\u6a0d\u6a0e\u6a0f\u6a10\u6a11\u6a12\u6a13\u6a14\u6a15\u6a16\u6a17\u6a18\u6a19\u6a1a\u6a1b\u6a1c\u6a1d\u6a1e\u6a1f\u6a20\u6a21\u6a22\u6a23\u6a24\u6a25\u6a26\u6a27\u6a28\u6a29\u6a2a\u6a2b\u6a2c\u6a2d\u6a2e\u6a2f\u6a30\u6a31\u6a32\u6a33\u6a34\u6a35\u6a36\u6a37\u6a38\u6a39\u6a3a\u6a3b\u6a3c\u6a3d\u6a3e\u6a3f\u6a40\u6a41\u6a42\u6a43\u6a44\u6a45\u6a46\u6a47\u6a48\u6a49\u6a4a\u6a4b\u6a4c\u6a4d\u6a4e\u6a4f\u6a50\u6a51\u6a52\u6a53\u6a54\u6a55\u6a56\u6a57\u6a58\u6a59\u6a5a\u6a5b\u6a5c\u6a5d\u6a5e\u6a5f\u6a60\u6a61\u6a62\u6a63\u6a64\u6a65\u6a66\u6a67\u6a68\u6a69\u6a6a\u6a6b\u6a6c\u6a6d\u6a6e\u6a6f\u6a70\u6a71\u6a72\u6a73\u6a74\u6a75\u6a76\u6a77\u6a78\u6a79\u6a7a\u6a7b\u6a7c\u6a7d\u6a7e\u6a7f\u6a80\u6a81\u6a82\u6a83\u6a84\u6a85\u6a86\u6a87\u6a88\u6a89\u6a8a\u6a8b\u6a8c\u6a8d\u6a8e\u6a8f\u6a90\u6a91\u6a92\u6a93\u6a94\u6a95\u6a96\u6a97\u6a98\u6a99\u6a9a\u6a9b\u6a9c\u6a9d\u6a9e\u6a9f\u6aa0\u6aa1\u6aa2\u6aa3\u6aa4\u6aa5\u6aa6\u6aa7\u6aa8\u6aa9\u6aaa\u6aab\u6aac\u6aad\u6aae\u6aaf\u6ab0\u6ab1\u6ab2\u6ab3\u6ab4\u6ab5\u6ab6\u6ab7\u6ab8\u6ab9\u6aba\u6abb\u6abc\u6abd\u6abe\u6abf\u6ac0\u6ac1\u6ac2\u6ac3\u6ac4\u6ac5\u6ac6\u6ac7\u6ac8\u6ac9\u6aca\u6acb\u6acc\u6acd\u6ace\u6acf\u6ad0\u6ad1\u6ad2\u6ad3\u6ad4\u6ad5\u6ad6\u6ad7\u6ad8\u6ad9\u6ada\u6adb\u6adc\u6add\u6ade\u6adf\u6ae0\u6ae1\u6ae2\u6ae3\u6ae4\u6ae5\u6ae6\u6ae7\u6ae8\u6ae9\u6aea\u6aeb\u6aec\u6aed\u6aee\u6aef\u6af0\u6af1\u6af2\u6af3\u6af4\u6af5\u6af6\u6af7\u6af8\u6af9\u6afa\u6afb\u6afc\u6afd\u6afe\u6aff\u6b00\u6b01\u6b02\u6b03\u6b04\u6b05\u6b06\u6b07\u6b08\u6b09\u6b0a\u6b0b\u6b0c\u6b0d\u6b0e\u6b0f\u6b10\u6b11\u6b12\u6b13\u6b14\u6b15\u6b16\u6b17\u6b18\u6b19\u6b1a\u6b1b\u6b1c\u6b1d\u6b1e\u6b1f\u6b20\u6b21\u6b22\u6b23\u6b24\u6b25\u6b26\u6b27\u6b28\u6b29\u6b2a\u6b2b\u6b2c\u6b2d\u6b2e\u6b2f\u6b30\u6b31\u6b32\u6b33\u6b34\u6b35\u6b36\u6b37\u6b38\u6b39\u6b3a\u6b3b\u6b3c\u6b3d\u6b3e\u6b3f\u6b40\u6b41\u6b42\u6b43\u6b44\u6b45\u6b46\u6b47\u6b48\u6b49\u6b4a\u6b4b\u6b4c\u6b4d\u6b4e\u6b4f\u6b50\u6b51\u6b52\u6b53\u6b54\u6b55\u6b56\u6b57\u6b58\u6b59\u6b5a\u6b5b\u6b5c\u6b5d\u6b5e\u6b5f\u6b60\u6b61\u6b62\u6b63\u6b64\u6b65\u6b66\u6b67\u6b68\u6b69\u6b6a\u6b6b\u6b6c\u6b6d\u6b6e\u6b6f\u6b70\u6b71\u6b72\u6b73\u6b74\u6b75\u6b76\u6b77\u6b78\u6b79\u6b7a\u6b7b\u6b7c\u6b7d\u6b7e\u6b7f\u6b80\u6b81\u6b82\u6b83\u6b84\u6b85\u6b86\u6b87\u6b88\u6b89\u6b8a\u6b8b\u6b8c\u6b8d\u6b8e\u6b8f\u6b90\u6b91\u6b92\u6b93\u6b94\u6b95\u6b96\u6b97\u6b98\u6b99\u6b9a\u6b9b\u6b9c\u6b9d\u6b9e\u6b9f\u6ba0\u6ba1\u6ba2\u6ba3\u6ba4\u6ba5\u6ba6\u6ba7\u6ba8\u6ba9\u6baa\u6bab\u6bac\u6bad\u6bae\u6baf\u6bb0\u6bb1\u6bb2\u6bb3\u6bb4\u6bb5\u6bb6\u6bb7\u6bb8\u6bb9\u6bba\u6bbb\u6bbc\u6bbd\u6bbe\u6bbf\u6bc0\u6bc1\u6bc2\u6bc3\u6bc4\u6bc5\u6bc6\u6bc7\u6bc8\u6bc9\u6bca\u6bcb\u6bcc\u6bcd\u6bce\u6bcf\u6bd0\u6bd1\u6bd2\u6bd3\u6bd4\u6bd5\u6bd6\u6bd7\u6bd8\u6bd9\u6bda\u6bdb\u6bdc\u6bdd\u6bde\u6bdf\u6be0\u6be1\u6be2\u6be3\u6be4\u6be5\u6be6\u6be7\u6be8\u6be9\u6bea\u6beb\u6bec\u6bed\u6bee\u6bef\u6bf0\u6bf1\u6bf2\u6bf3\u6bf4\u6bf5\u6bf6\u6bf7\u6bf8\u6bf9\u6bfa\u6bfb\u6bfc\u6bfd\u6bfe\u6bff\u6c00\u6c01\u6c02\u6c03\u6c04\u6c05\u6c06\u6c07\u6c08\u6c09\u6c0a\u6c0b\u6c0c\u6c0d\u6c0e\u6c0f\u6c10\u6c11\u6c12\u6c13\u6c14\u6c15\u6c16\u6c17\u6c18\u6c19\u6c1a\u6c1b\u6c1c\u6c1d\u6c1e\u6c1f\u6c20\u6c21\u6c22\u6c23\u6c24\u6c25\u6c26\u6c27\u6c28\u6c29\u6c2a\u6c2b\u6c2c\u6c2d\u6c2e\u6c2f\u6c30\u6c31\u6c32\u6c33\u6c34\u6c35\u6c36\u6c37\u6c38\u6c39\u6c3a\u6c3b\u6c3c\u6c3d\u6c3e\u6c3f\u6c40\u6c41\u6c42\u6c43\u6c44\u6c45\u6c46\u6c47\u6c48\u6c49\u6c4a\u6c4b\u6c4c\u6c4d\u6c4e\u6c4f\u6c50\u6c51\u6c52\u6c53\u6c54\u6c55\u6c56\u6c57\u6c58\u6c59\u6c5a\u6c5b\u6c5c\u6c5d\u6c5e\u6c5f\u6c60\u6c61\u6c62\u6c63\u6c64\u6c65\u6c66\u6c67\u6c68\u6c69\u6c6a\u6c6b\u6c6c\u6c6d\u6c6e\u6c6f\u6c70\u6c71\u6c72\u6c73\u6c74\u6c75\u6c76\u6c77\u6c78\u6c79\u6c7a\u6c7b\u6c7c\u6c7d\u6c7e\u6c7f\u6c80\u6c81\u6c82\u6c83\u6c84\u6c85\u6c86\u6c87\u6c88\u6c89\u6c8a\u6c8b\u6c8c\u6c8d\u6c8e\u6c8f\u6c90\u6c91\u6c92\u6c93\u6c94\u6c95\u6c96\u6c97\u6c98\u6c99\u6c9a\u6c9b\u6c9c\u6c9d\u6c9e\u6c9f\u6ca0\u6ca1\u6ca2\u6ca3\u6ca4\u6ca5\u6ca6\u6ca7\u6ca8\u6ca9\u6caa\u6cab\u6cac\u6cad\u6cae\u6caf\u6cb0\u6cb1\u6cb2\u6cb3\u6cb4\u6cb5\u6cb6\u6cb7\u6cb8\u6cb9\u6cba\u6cbb\u6cbc\u6cbd\u6cbe\u6cbf\u6cc0\u6cc1\u6cc2\u6cc3\u6cc4\u6cc5\u6cc6\u6cc7\u6cc8\u6cc9\u6cca\u6ccb\u6ccc\u6ccd\u6cce\u6ccf\u6cd0\u6cd1\u6cd2\u6cd3\u6cd4\u6cd5\u6cd6\u6cd7\u6cd8\u6cd9\u6cda\u6cdb\u6cdc\u6cdd\u6cde\u6cdf\u6ce0\u6ce1\u6ce2\u6ce3\u6ce4\u6ce5\u6ce6\u6ce7\u6ce8\u6ce9\u6cea\u6ceb\u6cec\u6ced\u6cee\u6cef\u6cf0\u6cf1\u6cf2\u6cf3\u6cf4\u6cf5\u6cf6\u6cf7\u6cf8\u6cf9\u6cfa\u6cfb\u6cfc\u6cfd\u6cfe\u6cff\u6d00\u6d01\u6d02\u6d03\u6d04\u6d05\u6d06\u6d07\u6d08\u6d09\u6d0a\u6d0b\u6d0c\u6d0d\u6d0e\u6d0f\u6d10\u6d11\u6d12\u6d13\u6d14\u6d15\u6d16\u6d17\u6d18\u6d19\u6d1a\u6d1b\u6d1c\u6d1d\u6d1e\u6d1f\u6d20\u6d21\u6d22\u6d23\u6d24\u6d25\u6d26\u6d27\u6d28\u6d29\u6d2a\u6d2b\u6d2c\u6d2d\u6d2e\u6d2f\u6d30\u6d31\u6d32\u6d33\u6d34\u6d35\u6d36\u6d37\u6d38\u6d39\u6d3a\u6d3b\u6d3c\u6d3d\u6d3e\u6d3f\u6d40\u6d41\u6d42\u6d43\u6d44\u6d45\u6d46\u6d47\u6d48\u6d49\u6d4a\u6d4b\u6d4c\u6d4d\u6d4e\u6d4f\u6d50\u6d51\u6d52\u6d53\u6d54\u6d55\u6d56\u6d57\u6d58\u6d59\u6d5a\u6d5b\u6d5c\u6d5d\u6d5e\u6d5f\u6d60\u6d61\u6d62\u6d63\u6d64\u6d65\u6d66\u6d67\u6d68\u6d69\u6d6a\u6d6b\u6d6c\u6d6d\u6d6e\u6d6f\u6d70\u6d71\u6d72\u6d73\u6d74\u6d75\u6d76\u6d77\u6d78\u6d79\u6d7a\u6d7b\u6d7c\u6d7d\u6d7e\u6d7f\u6d80\u6d81\u6d82\u6d83\u6d84\u6d85\u6d86\u6d87\u6d88\u6d89\u6d8a\u6d8b\u6d8c\u6d8d\u6d8e\u6d8f\u6d90\u6d91\u6d92\u6d93\u6d94\u6d95\u6d96\u6d97\u6d98\u6d99\u6d9a\u6d9b\u6d9c\u6d9d\u6d9e\u6d9f\u6da0\u6da1\u6da2\u6da3\u6da4\u6da5\u6da6\u6da7\u6da8\u6da9\u6daa\u6dab\u6dac\u6dad\u6dae\u6daf\u6db0\u6db1\u6db2\u6db3\u6db4\u6db5\u6db6\u6db7\u6db8\u6db9\u6dba\u6dbb\u6dbc\u6dbd\u6dbe\u6dbf\u6dc0\u6dc1\u6dc2\u6dc3\u6dc4\u6dc5\u6dc6\u6dc7\u6dc8\u6dc9\u6dca\u6dcb\u6dcc\u6dcd\u6dce\u6dcf\u6dd0\u6dd1\u6dd2\u6dd3\u6dd4\u6dd5\u6dd6\u6dd7\u6dd8\u6dd9\u6dda\u6ddb\u6ddc\u6ddd\u6dde\u6ddf\u6de0\u6de1\u6de2\u6de3\u6de4\u6de5\u6de6\u6de7\u6de8\u6de9\u6dea\u6deb\u6dec\u6ded\u6dee\u6def\u6df0\u6df1\u6df2\u6df3\u6df4\u6df5\u6df6\u6df7\u6df8\u6df9\u6dfa\u6dfb\u6dfc\u6dfd\u6dfe\u6dff\u6e00\u6e01\u6e02\u6e03\u6e04\u6e05\u6e06\u6e07\u6e08\u6e09\u6e0a\u6e0b\u6e0c\u6e0d\u6e0e\u6e0f\u6e10\u6e11\u6e12\u6e13\u6e14\u6e15\u6e16\u6e17\u6e18\u6e19\u6e1a\u6e1b\u6e1c\u6e1d\u6e1e\u6e1f\u6e20\u6e21\u6e22\u6e23\u6e24\u6e25\u6e26\u6e27\u6e28\u6e29\u6e2a\u6e2b\u6e2c\u6e2d\u6e2e\u6e2f\u6e30\u6e31\u6e32\u6e33\u6e34\u6e35\u6e36\u6e37\u6e38\u6e39\u6e3a\u6e3b\u6e3c\u6e3d\u6e3e\u6e3f\u6e40\u6e41\u6e42\u6e43\u6e44\u6e45\u6e46\u6e47\u6e48\u6e49\u6e4a\u6e4b\u6e4c\u6e4d\u6e4e\u6e4f\u6e50\u6e51\u6e52\u6e53\u6e54\u6e55\u6e56\u6e57\u6e58\u6e59\u6e5a\u6e5b\u6e5c\u6e5d\u6e5e\u6e5f\u6e60\u6e61\u6e62\u6e63\u6e64\u6e65\u6e66\u6e67\u6e68\u6e69\u6e6a\u6e6b\u6e6c\u6e6d\u6e6e\u6e6f\u6e70\u6e71\u6e72\u6e73\u6e74\u6e75\u6e76\u6e77\u6e78\u6e79\u6e7a\u6e7b\u6e7c\u6e7d\u6e7e\u6e7f\u6e80\u6e81\u6e82\u6e83\u6e84\u6e85\u6e86\u6e87\u6e88\u6e89\u6e8a\u6e8b\u6e8c\u6e8d\u6e8e\u6e8f\u6e90\u6e91\u6e92\u6e93\u6e94\u6e95\u6e96\u6e97\u6e98\u6e99\u6e9a\u6e9b\u6e9c\u6e9d\u6e9e\u6e9f\u6ea0\u6ea1\u6ea2\u6ea3\u6ea4\u6ea5\u6ea6\u6ea7\u6ea8\u6ea9\u6eaa\u6eab\u6eac\u6ead\u6eae\u6eaf\u6eb0\u6eb1\u6eb2\u6eb3\u6eb4\u6eb5\u6eb6\u6eb7\u6eb8\u6eb9\u6eba\u6ebb\u6ebc\u6ebd\u6ebe\u6ebf\u6ec0\u6ec1\u6ec2\u6ec3\u6ec4\u6ec5\u6ec6\u6ec7\u6ec8\u6ec9\u6eca\u6ecb\u6ecc\u6ecd\u6ece\u6ecf\u6ed0\u6ed1\u6ed2\u6ed3\u6ed4\u6ed5\u6ed6\u6ed7\u6ed8\u6ed9\u6eda\u6edb\u6edc\u6edd\u6ede\u6edf\u6ee0\u6ee1\u6ee2\u6ee3\u6ee4\u6ee5\u6ee6\u6ee7\u6ee8\u6ee9\u6eea\u6eeb\u6eec\u6eed\u6eee\u6eef\u6ef0\u6ef1\u6ef2\u6ef3\u6ef4\u6ef5\u6ef6\u6ef7\u6ef8\u6ef9\u6efa\u6efb\u6efc\u6efd\u6efe\u6eff\u6f00\u6f01\u6f02\u6f03\u6f04\u6f05\u6f06\u6f07\u6f08\u6f09\u6f0a\u6f0b\u6f0c\u6f0d\u6f0e\u6f0f\u6f10\u6f11\u6f12\u6f13\u6f14\u6f15\u6f16\u6f17\u6f18\u6f19\u6f1a\u6f1b\u6f1c\u6f1d\u6f1e\u6f1f\u6f20\u6f21\u6f22\u6f23\u6f24\u6f25\u6f26\u6f27\u6f28\u6f29\u6f2a\u6f2b\u6f2c\u6f2d\u6f2e\u6f2f\u6f30\u6f31\u6f32\u6f33\u6f34\u6f35\u6f36\u6f37\u6f38\u6f39\u6f3a\u6f3b\u6f3c\u6f3d\u6f3e\u6f3f\u6f40\u6f41\u6f42\u6f43\u6f44\u6f45\u6f46\u6f47\u6f48\u6f49\u6f4a\u6f4b\u6f4c\u6f4d\u6f4e\u6f4f\u6f50\u6f51\u6f52\u6f53\u6f54\u6f55\u6f56\u6f57\u6f58\u6f59\u6f5a\u6f5b\u6f5c\u6f5d\u6f5e\u6f5f\u6f60\u6f61\u6f62\u6f63\u6f64\u6f65\u6f66\u6f67\u6f68\u6f69\u6f6a\u6f6b\u6f6c\u6f6d\u6f6e\u6f6f\u6f70\u6f71\u6f72\u6f73\u6f74\u6f75\u6f76\u6f77\u6f78\u6f79\u6f7a\u6f7b\u6f7c\u6f7d\u6f7e\u6f7f\u6f80\u6f81\u6f82\u6f83\u6f84\u6f85\u6f86\u6f87\u6f88\u6f89\u6f8a\u6f8b\u6f8c\u6f8d\u6f8e\u6f8f\u6f90\u6f91\u6f92\u6f93\u6f94\u6f95\u6f96\u6f97\u6f98\u6f99\u6f9a\u6f9b\u6f9c\u6f9d\u6f9e\u6f9f\u6fa0\u6fa1\u6fa2\u6fa3\u6fa4\u6fa5\u6fa6\u6fa7\u6fa8\u6fa9\u6faa\u6fab\u6fac\u6fad\u6fae\u6faf\u6fb0\u6fb1\u6fb2\u6fb3\u6fb4\u6fb5\u6fb6\u6fb7\u6fb8\u6fb9\u6fba\u6fbb\u6fbc\u6fbd\u6fbe\u6fbf\u6fc0\u6fc1\u6fc2\u6fc3\u6fc4\u6fc5\u6fc6\u6fc7\u6fc8\u6fc9\u6fca\u6fcb\u6fcc\u6fcd\u6fce\u6fcf\u6fd0\u6fd1\u6fd2\u6fd3\u6fd4\u6fd5\u6fd6\u6fd7\u6fd8\u6fd9\u6fda\u6fdb\u6fdc\u6fdd\u6fde\u6fdf\u6fe0\u6fe1\u6fe2\u6fe3\u6fe4\u6fe5\u6fe6\u6fe7\u6fe8\u6fe9\u6fea\u6feb\u6fec\u6fed\u6fee\u6fef\u6ff0\u6ff1\u6ff2\u6ff3\u6ff4\u6ff5\u6ff6\u6ff7\u6ff8\u6ff9\u6ffa\u6ffb\u6ffc\u6ffd\u6ffe\u6fff\u7000\u7001\u7002\u7003\u7004\u7005\u7006\u7007\u7008\u7009\u700a\u700b\u700c\u700d\u700e\u700f\u7010\u7011\u7012\u7013\u7014\u7015\u7016\u7017\u7018\u7019\u701a\u701b\u701c\u701d\u701e\u701f\u7020\u7021\u7022\u7023\u7024\u7025\u7026\u7027\u7028\u7029\u702a\u702b\u702c\u702d\u702e\u702f\u7030\u7031\u7032\u7033\u7034\u7035\u7036\u7037\u7038\u7039\u703a\u703b\u703c\u703d\u703e\u703f\u7040\u7041\u7042\u7043\u7044\u7045\u7046\u7047\u7048\u7049\u704a\u704b\u704c\u704d\u704e\u704f\u7050\u7051\u7052\u7053\u7054\u7055\u7056\u7057\u7058\u7059\u705a\u705b\u705c\u705d\u705e\u705f\u7060\u7061\u7062\u7063\u7064\u7065\u7066\u7067\u7068\u7069\u706a\u706b\u706c\u706d\u706e\u706f\u7070\u7071\u7072\u7073\u7074\u7075\u7076\u7077\u7078\u7079\u707a\u707b\u707c\u707d\u707e\u707f\u7080\u7081\u7082\u7083\u7084\u7085\u7086\u7087\u7088\u7089\u708a\u708b\u708c\u708d\u708e\u708f\u7090\u7091\u7092\u7093\u7094\u7095\u7096\u7097\u7098\u7099\u709a\u709b\u709c\u709d\u709e\u709f\u70a0\u70a1\u70a2\u70a3\u70a4\u70a5\u70a6\u70a7\u70a8\u70a9\u70aa\u70ab\u70ac\u70ad\u70ae\u70af\u70b0\u70b1\u70b2\u70b3\u70b4\u70b5\u70b6\u70b7\u70b8\u70b9\u70ba\u70bb\u70bc\u70bd\u70be\u70bf\u70c0\u70c1\u70c2\u70c3\u70c4\u70c5\u70c6\u70c7\u70c8\u70c9\u70ca\u70cb\u70cc\u70cd\u70ce\u70cf\u70d0\u70d1\u70d2\u70d3\u70d4\u70d5\u70d6\u70d7\u70d8\u70d9\u70da\u70db\u70dc\u70dd\u70de\u70df\u70e0\u70e1\u70e2\u70e3\u70e4\u70e5\u70e6\u70e7\u70e8\u70e9\u70ea\u70eb\u70ec\u70ed\u70ee\u70ef\u70f0\u70f1\u70f2\u70f3\u70f4\u70f5\u70f6\u70f7\u70f8\u70f9\u70fa\u70fb\u70fc\u70fd\u70fe\u70ff\u7100\u7101\u7102\u7103\u7104\u7105\u7106\u7107\u7108\u7109\u710a\u710b\u710c\u710d\u710e\u710f\u7110\u7111\u7112\u7113\u7114\u7115\u7116\u7117\u7118\u7119\u711a\u711b\u711c\u711d\u711e\u711f\u7120\u7121\u7122\u7123\u7124\u7125\u7126\u7127\u7128\u7129\u712a\u712b\u712c\u712d\u712e\u712f\u7130\u7131\u7132\u7133\u7134\u7135\u7136\u7137\u7138\u7139\u713a\u713b\u713c\u713d\u713e\u713f\u7140\u7141\u7142\u7143\u7144\u7145\u7146\u7147\u7148\u7149\u714a\u714b\u714c\u714d\u714e\u714f\u7150\u7151\u7152\u7153\u7154\u7155\u7156\u7157\u7158\u7159\u715a\u715b\u715c\u715d\u715e\u715f\u7160\u7161\u7162\u7163\u7164\u7165\u7166\u7167\u7168\u7169\u716a\u716b\u716c\u716d\u716e\u716f\u7170\u7171\u7172\u7173\u7174\u7175\u7176\u7177\u7178\u7179\u717a\u717b\u717c\u717d\u717e\u717f\u7180\u7181\u7182\u7183\u7184\u7185\u7186\u7187\u7188\u7189\u718a\u718b\u718c\u718d\u718e\u718f\u7190\u7191\u7192\u7193\u7194\u7195\u7196\u7197\u7198\u7199\u719a\u719b\u719c\u719d\u719e\u719f\u71a0\u71a1\u71a2\u71a3\u71a4\u71a5\u71a6\u71a7\u71a8\u71a9\u71aa\u71ab\u71ac\u71ad\u71ae\u71af\u71b0\u71b1\u71b2\u71b3\u71b4\u71b5\u71b6\u71b7\u71b8\u71b9\u71ba\u71bb\u71bc\u71bd\u71be\u71bf\u71c0\u71c1\u71c2\u71c3\u71c4\u71c5\u71c6\u71c7\u71c8\u71c9\u71ca\u71cb\u71cc\u71cd\u71ce\u71cf\u71d0\u71d1\u71d2\u71d3\u71d4\u71d5\u71d6\u71d7\u71d8\u71d9\u71da\u71db\u71dc\u71dd\u71de\u71df\u71e0\u71e1\u71e2\u71e3\u71e4\u71e5\u71e6\u71e7\u71e8\u71e9\u71ea\u71eb\u71ec\u71ed\u71ee\u71ef\u71f0\u71f1\u71f2\u71f3\u71f4\u71f5\u71f6\u71f7\u71f8\u71f9\u71fa\u71fb\u71fc\u71fd\u71fe\u71ff\u7200\u7201\u7202\u7203\u7204\u7205\u7206\u7207\u7208\u7209\u720a\u720b\u720c\u720d\u720e\u720f\u7210\u7211\u7212\u7213\u7214\u7215\u7216\u7217\u7218\u7219\u721a\u721b\u721c\u721d\u721e\u721f\u7220\u7221\u7222\u7223\u7224\u7225\u7226\u7227\u7228\u7229\u722a\u722b\u722c\u722d\u722e\u722f\u7230\u7231\u7232\u7233\u7234\u7235\u7236\u7237\u7238\u7239\u723a\u723b\u723c\u723d\u723e\u723f\u7240\u7241\u7242\u7243\u7244\u7245\u7246\u7247\u7248\u7249\u724a\u724b\u724c\u724d\u724e\u724f\u7250\u7251\u7252\u7253\u7254\u7255\u7256\u7257\u7258\u7259\u725a\u725b\u725c\u725d\u725e\u725f\u7260\u7261\u7262\u7263\u7264\u7265\u7266\u7267\u7268\u7269\u726a\u726b\u726c\u726d\u726e\u726f\u7270\u7271\u7272\u7273\u7274\u7275\u7276\u7277\u7278\u7279\u727a\u727b\u727c\u727d\u727e\u727f\u7280\u7281\u7282\u7283\u7284\u7285\u7286\u7287\u7288\u7289\u728a\u728b\u728c\u728d\u728e\u728f\u7290\u7291\u7292\u7293\u7294\u7295\u7296\u7297\u7298\u7299\u729a\u729b\u729c\u729d\u729e\u729f\u72a0\u72a1\u72a2\u72a3\u72a4\u72a5\u72a6\u72a7\u72a8\u72a9\u72aa\u72ab\u72ac\u72ad\u72ae\u72af\u72b0\u72b1\u72b2\u72b3\u72b4\u72b5\u72b6\u72b7\u72b8\u72b9\u72ba\u72bb\u72bc\u72bd\u72be\u72bf\u72c0\u72c1\u72c2\u72c3\u72c4\u72c5\u72c6\u72c7\u72c8\u72c9\u72ca\u72cb\u72cc\u72cd\u72ce\u72cf\u72d0\u72d1\u72d2\u72d3\u72d4\u72d5\u72d6\u72d7\u72d8\u72d9\u72da\u72db\u72dc\u72dd\u72de\u72df\u72e0\u72e1\u72e2\u72e3\u72e4\u72e5\u72e6\u72e7\u72e8\u72e9\u72ea\u72eb\u72ec\u72ed\u72ee\u72ef\u72f0\u72f1\u72f2\u72f3\u72f4\u72f5\u72f6\u72f7\u72f8\u72f9\u72fa\u72fb\u72fc\u72fd\u72fe\u72ff\u7300\u7301\u7302\u7303\u7304\u7305\u7306\u7307\u7308\u7309\u730a\u730b\u730c\u730d\u730e\u730f\u7310\u7311\u7312\u7313\u7314\u7315\u7316\u7317\u7318\u7319\u731a\u731b\u731c\u731d\u731e\u731f\u7320\u7321\u7322\u7323\u7324\u7325\u7326\u7327\u7328\u7329\u732a\u732b\u732c\u732d\u732e\u732f\u7330\u7331\u7332\u7333\u7334\u7335\u7336\u7337\u7338\u7339\u733a\u733b\u733c\u733d\u733e\u733f\u7340\u7341\u7342\u7343\u7344\u7345\u7346\u7347\u7348\u7349\u734a\u734b\u734c\u734d\u734e\u734f\u7350\u7351\u7352\u7353\u7354\u7355\u7356\u7357\u7358\u7359\u735a\u735b\u735c\u735d\u735e\u735f\u7360\u7361\u7362\u7363\u7364\u7365\u7366\u7367\u7368\u7369\u736a\u736b\u736c\u736d\u736e\u736f\u7370\u7371\u7372\u7373\u7374\u7375\u7376\u7377\u7378\u7379\u737a\u737b\u737c\u737d\u737e\u737f\u7380\u7381\u7382\u7383\u7384\u7385\u7386\u7387\u7388\u7389\u738a\u738b\u738c\u738d\u738e\u738f\u7390\u7391\u7392\u7393\u7394\u7395\u7396\u7397\u7398\u7399\u739a\u739b\u739c\u739d\u739e\u739f\u73a0\u73a1\u73a2\u73a3\u73a4\u73a5\u73a6\u73a7\u73a8\u73a9\u73aa\u73ab\u73ac\u73ad\u73ae\u73af\u73b0\u73b1\u73b2\u73b3\u73b4\u73b5\u73b6\u73b7\u73b8\u73b9\u73ba\u73bb\u73bc\u73bd\u73be\u73bf\u73c0\u73c1\u73c2\u73c3\u73c4\u73c5\u73c6\u73c7\u73c8\u73c9\u73ca\u73cb\u73cc\u73cd\u73ce\u73cf\u73d0\u73d1\u73d2\u73d3\u73d4\u73d5\u73d6\u73d7\u73d8\u73d9\u73da\u73db\u73dc\u73dd\u73de\u73df\u73e0\u73e1\u73e2\u73e3\u73e4\u73e5\u73e6\u73e7\u73e8\u73e9\u73ea\u73eb\u73ec\u73ed\u73ee\u73ef\u73f0\u73f1\u73f2\u73f3\u73f4\u73f5\u73f6\u73f7\u73f8\u73f9\u73fa\u73fb\u73fc\u73fd\u73fe\u73ff\u7400\u7401\u7402\u7403\u7404\u7405\u7406\u7407\u7408\u7409\u740a\u740b\u740c\u740d\u740e\u740f\u7410\u7411\u7412\u7413\u7414\u7415\u7416\u7417\u7418\u7419\u741a\u741b\u741c\u741d\u741e\u741f\u7420\u7421\u7422\u7423\u7424\u7425\u7426\u7427\u7428\u7429\u742a\u742b\u742c\u742d\u742e\u742f\u7430\u7431\u7432\u7433\u7434\u7435\u7436\u7437\u7438\u7439\u743a\u743b\u743c\u743d\u743e\u743f\u7440\u7441\u7442\u7443\u7444\u7445\u7446\u7447\u7448\u7449\u744a\u744b\u744c\u744d\u744e\u744f\u7450\u7451\u7452\u7453\u7454\u7455\u7456\u7457\u7458\u7459\u745a\u745b\u745c\u745d\u745e\u745f\u7460\u7461\u7462\u7463\u7464\u7465\u7466\u7467\u7468\u7469\u746a\u746b\u746c\u746d\u746e\u746f\u7470\u7471\u7472\u7473\u7474\u7475\u7476\u7477\u7478\u7479\u747a\u747b\u747c\u747d\u747e\u747f\u7480\u7481\u7482\u7483\u7484\u7485\u7486\u7487\u7488\u7489\u748a\u748b\u748c\u748d\u748e\u748f\u7490\u7491\u7492\u7493\u7494\u7495\u7496\u7497\u7498\u7499\u749a\u749b\u749c\u749d\u749e\u749f\u74a0\u74a1\u74a2\u74a3\u74a4\u74a5\u74a6\u74a7\u74a8\u74a9\u74aa\u74ab\u74ac\u74ad\u74ae\u74af\u74b0\u74b1\u74b2\u74b3\u74b4\u74b5\u74b6\u74b7\u74b8\u74b9\u74ba\u74bb\u74bc\u74bd\u74be\u74bf\u74c0\u74c1\u74c2\u74c3\u74c4\u74c5\u74c6\u74c7\u74c8\u74c9\u74ca\u74cb\u74cc\u74cd\u74ce\u74cf\u74d0\u74d1\u74d2\u74d3\u74d4\u74d5\u74d6\u74d7\u74d8\u74d9\u74da\u74db\u74dc\u74dd\u74de\u74df\u74e0\u74e1\u74e2\u74e3\u74e4\u74e5\u74e6\u74e7\u74e8\u74e9\u74ea\u74eb\u74ec\u74ed\u74ee\u74ef\u74f0\u74f1\u74f2\u74f3\u74f4\u74f5\u74f6\u74f7\u74f8\u74f9\u74fa\u74fb\u74fc\u74fd\u74fe\u74ff\u7500\u7501\u7502\u7503\u7504\u7505\u7506\u7507\u7508\u7509\u750a\u750b\u750c\u750d\u750e\u750f\u7510\u7511\u7512\u7513\u7514\u7515\u7516\u7517\u7518\u7519\u751a\u751b\u751c\u751d\u751e\u751f\u7520\u7521\u7522\u7523\u7524\u7525\u7526\u7527\u7528\u7529\u752a\u752b\u752c\u752d\u752e\u752f\u7530\u7531\u7532\u7533\u7534\u7535\u7536\u7537\u7538\u7539\u753a\u753b\u753c\u753d\u753e\u753f\u7540\u7541\u7542\u7543\u7544\u7545\u7546\u7547\u7548\u7549\u754a\u754b\u754c\u754d\u754e\u754f\u7550\u7551\u7552\u7553\u7554\u7555\u7556\u7557\u7558\u7559\u755a\u755b\u755c\u755d\u755e\u755f\u7560\u7561\u7562\u7563\u7564\u7565\u7566\u7567\u7568\u7569\u756a\u756b\u756c\u756d\u756e\u756f\u7570\u7571\u7572\u7573\u7574\u7575\u7576\u7577\u7578\u7579\u757a\u757b\u757c\u757d\u757e\u757f\u7580\u7581\u7582\u7583\u7584\u7585\u7586\u7587\u7588\u7589\u758a\u758b\u758c\u758d\u758e\u758f\u7590\u7591\u7592\u7593\u7594\u7595\u7596\u7597\u7598\u7599\u759a\u759b\u759c\u759d\u759e\u759f\u75a0\u75a1\u75a2\u75a3\u75a4\u75a5\u75a6\u75a7\u75a8\u75a9\u75aa\u75ab\u75ac\u75ad\u75ae\u75af\u75b0\u75b1\u75b2\u75b3\u75b4\u75b5\u75b6\u75b7\u75b8\u75b9\u75ba\u75bb\u75bc\u75bd\u75be\u75bf\u75c0\u75c1\u75c2\u75c3\u75c4\u75c5\u75c6\u75c7\u75c8\u75c9\u75ca\u75cb\u75cc\u75cd\u75ce\u75cf\u75d0\u75d1\u75d2\u75d3\u75d4\u75d5\u75d6\u75d7\u75d8\u75d9\u75da\u75db\u75dc\u75dd\u75de\u75df\u75e0\u75e1\u75e2\u75e3\u75e4\u75e5\u75e6\u75e7\u75e8\u75e9\u75ea\u75eb\u75ec\u75ed\u75ee\u75ef\u75f0\u75f1\u75f2\u75f3\u75f4\u75f5\u75f6\u75f7\u75f8\u75f9\u75fa\u75fb\u75fc\u75fd\u75fe\u75ff\u7600\u7601\u7602\u7603\u7604\u7605\u7606\u7607\u7608\u7609\u760a\u760b\u760c\u760d\u760e\u760f\u7610\u7611\u7612\u7613\u7614\u7615\u7616\u7617\u7618\u7619\u761a\u761b\u761c\u761d\u761e\u761f\u7620\u7621\u7622\u7623\u7624\u7625\u7626\u7627\u7628\u7629\u762a\u762b\u762c\u762d\u762e\u762f\u7630\u7631\u7632\u7633\u7634\u7635\u7636\u7637\u7638\u7639\u763a\u763b\u763c\u763d\u763e\u763f\u7640\u7641\u7642\u7643\u7644\u7645\u7646\u7647\u7648\u7649\u764a\u764b\u764c\u764d\u764e\u764f\u7650\u7651\u7652\u7653\u7654\u7655\u7656\u7657\u7658\u7659\u765a\u765b\u765c\u765d\u765e\u765f\u7660\u7661\u7662\u7663\u7664\u7665\u7666\u7667\u7668\u7669\u766a\u766b\u766c\u766d\u766e\u766f\u7670\u7671\u7672\u7673\u7674\u7675\u7676\u7677\u7678\u7679\u767a\u767b\u767c\u767d\u767e\u767f\u7680\u7681\u7682\u7683\u7684\u7685\u7686\u7687\u7688\u7689\u768a\u768b\u768c\u768d\u768e\u768f\u7690\u7691\u7692\u7693\u7694\u7695\u7696\u7697\u7698\u7699\u769a\u769b\u769c\u769d\u769e\u769f\u76a0\u76a1\u76a2\u76a3\u76a4\u76a5\u76a6\u76a7\u76a8\u76a9\u76aa\u76ab\u76ac\u76ad\u76ae\u76af\u76b0\u76b1\u76b2\u76b3\u76b4\u76b5\u76b6\u76b7\u76b8\u76b9\u76ba\u76bb\u76bc\u76bd\u76be\u76bf\u76c0\u76c1\u76c2\u76c3\u76c4\u76c5\u76c6\u76c7\u76c8\u76c9\u76ca\u76cb\u76cc\u76cd\u76ce\u76cf\u76d0\u76d1\u76d2\u76d3\u76d4\u76d5\u76d6\u76d7\u76d8\u76d9\u76da\u76db\u76dc\u76dd\u76de\u76df\u76e0\u76e1\u76e2\u76e3\u76e4\u76e5\u76e6\u76e7\u76e8\u76e9\u76ea\u76eb\u76ec\u76ed\u76ee\u76ef\u76f0\u76f1\u76f2\u76f3\u76f4\u76f5\u76f6\u76f7\u76f8\u76f9\u76fa\u76fb\u76fc\u76fd\u76fe\u76ff\u7700\u7701\u7702\u7703\u7704\u7705\u7706\u7707\u7708\u7709\u770a\u770b\u770c\u770d\u770e\u770f\u7710\u7711\u7712\u7713\u7714\u7715\u7716\u7717\u7718\u7719\u771a\u771b\u771c\u771d\u771e\u771f\u7720\u7721\u7722\u7723\u7724\u7725\u7726\u7727\u7728\u7729\u772a\u772b\u772c\u772d\u772e\u772f\u7730\u7731\u7732\u7733\u7734\u7735\u7736\u7737\u7738\u7739\u773a\u773b\u773c\u773d\u773e\u773f\u7740\u7741\u7742\u7743\u7744\u7745\u7746\u7747\u7748\u7749\u774a\u774b\u774c\u774d\u774e\u774f\u7750\u7751\u7752\u7753\u7754\u7755\u7756\u7757\u7758\u7759\u775a\u775b\u775c\u775d\u775e\u775f\u7760\u7761\u7762\u7763\u7764\u7765\u7766\u7767\u7768\u7769\u776a\u776b\u776c\u776d\u776e\u776f\u7770\u7771\u7772\u7773\u7774\u7775\u7776\u7777\u7778\u7779\u777a\u777b\u777c\u777d\u777e\u777f\u7780\u7781\u7782\u7783\u7784\u7785\u7786\u7787\u7788\u7789\u778a\u778b\u778c\u778d\u778e\u778f\u7790\u7791\u7792\u7793\u7794\u7795\u7796\u7797\u7798\u7799\u779a\u779b\u779c\u779d\u779e\u779f\u77a0\u77a1\u77a2\u77a3\u77a4\u77a5\u77a6\u77a7\u77a8\u77a9\u77aa\u77ab\u77ac\u77ad\u77ae\u77af\u77b0\u77b1\u77b2\u77b3\u77b4\u77b5\u77b6\u77b7\u77b8\u77b9\u77ba\u77bb\u77bc\u77bd\u77be\u77bf\u77c0\u77c1\u77c2\u77c3\u77c4\u77c5\u77c6\u77c7\u77c8\u77c9\u77ca\u77cb\u77cc\u77cd\u77ce\u77cf\u77d0\u77d1\u77d2\u77d3\u77d4\u77d5\u77d6\u77d7\u77d8\u77d9\u77da\u77db\u77dc\u77dd\u77de\u77df\u77e0\u77e1\u77e2\u77e3\u77e4\u77e5\u77e6\u77e7\u77e8\u77e9\u77ea\u77eb\u77ec\u77ed\u77ee\u77ef\u77f0\u77f1\u77f2\u77f3\u77f4\u77f5\u77f6\u77f7\u77f8\u77f9\u77fa\u77fb\u77fc\u77fd\u77fe\u77ff\u7800\u7801\u7802\u7803\u7804\u7805\u7806\u7807\u7808\u7809\u780a\u780b\u780c\u780d\u780e\u780f\u7810\u7811\u7812\u7813\u7814\u7815\u7816\u7817\u7818\u7819\u781a\u781b\u781c\u781d\u781e\u781f\u7820\u7821\u7822\u7823\u7824\u7825\u7826\u7827\u7828\u7829\u782a\u782b\u782c\u782d\u782e\u782f\u7830\u7831\u7832\u7833\u7834\u7835\u7836\u7837\u7838\u7839\u783a\u783b\u783c\u783d\u783e\u783f\u7840\u7841\u7842\u7843\u7844\u7845\u7846\u7847\u7848\u7849\u784a\u784b\u784c\u784d\u784e\u784f\u7850\u7851\u7852\u7853\u7854\u7855\u7856\u7857\u7858\u7859\u785a\u785b\u785c\u785d\u785e\u785f\u7860\u7861\u7862\u7863\u7864\u7865\u7866\u7867\u7868\u7869\u786a\u786b\u786c\u786d\u786e\u786f\u7870\u7871\u7872\u7873\u7874\u7875\u7876\u7877\u7878\u7879\u787a\u787b\u787c\u787d\u787e\u787f\u7880\u7881\u7882\u7883\u7884\u7885\u7886\u7887\u7888\u7889\u788a\u788b\u788c\u788d\u788e\u788f\u7890\u7891\u7892\u7893\u7894\u7895\u7896\u7897\u7898\u7899\u789a\u789b\u789c\u789d\u789e\u789f\u78a0\u78a1\u78a2\u78a3\u78a4\u78a5\u78a6\u78a7\u78a8\u78a9\u78aa\u78ab\u78ac\u78ad\u78ae\u78af\u78b0\u78b1\u78b2\u78b3\u78b4\u78b5\u78b6\u78b7\u78b8\u78b9\u78ba\u78bb\u78bc\u78bd\u78be\u78bf\u78c0\u78c1\u78c2\u78c3\u78c4\u78c5\u78c6\u78c7\u78c8\u78c9\u78ca\u78cb\u78cc\u78cd\u78ce\u78cf\u78d0\u78d1\u78d2\u78d3\u78d4\u78d5\u78d6\u78d7\u78d8\u78d9\u78da\u78db\u78dc\u78dd\u78de\u78df\u78e0\u78e1\u78e2\u78e3\u78e4\u78e5\u78e6\u78e7\u78e8\u78e9\u78ea\u78eb\u78ec\u78ed\u78ee\u78ef\u78f0\u78f1\u78f2\u78f3\u78f4\u78f5\u78f6\u78f7\u78f8\u78f9\u78fa\u78fb\u78fc\u78fd\u78fe\u78ff\u7900\u7901\u7902\u7903\u7904\u7905\u7906\u7907\u7908\u7909\u790a\u790b\u790c\u790d\u790e\u790f\u7910\u7911\u7912\u7913\u7914\u7915\u7916\u7917\u7918\u7919\u791a\u791b\u791c\u791d\u791e\u791f\u7920\u7921\u7922\u7923\u7924\u7925\u7926\u7927\u7928\u7929\u792a\u792b\u792c\u792d\u792e\u792f\u7930\u7931\u7932\u7933\u7934\u7935\u7936\u7937\u7938\u7939\u793a\u793b\u793c\u793d\u793e\u793f\u7940\u7941\u7942\u7943\u7944\u7945\u7946\u7947\u7948\u7949\u794a\u794b\u794c\u794d\u794e\u794f\u7950\u7951\u7952\u7953\u7954\u7955\u7956\u7957\u7958\u7959\u795a\u795b\u795c\u795d\u795e\u795f\u7960\u7961\u7962\u7963\u7964\u7965\u7966\u7967\u7968\u7969\u796a\u796b\u796c\u796d\u796e\u796f\u7970\u7971\u7972\u7973\u7974\u7975\u7976\u7977\u7978\u7979\u797a\u797b\u797c\u797d\u797e\u797f\u7980\u7981\u7982\u7983\u7984\u7985\u7986\u7987\u7988\u7989\u798a\u798b\u798c\u798d\u798e\u798f\u7990\u7991\u7992\u7993\u7994\u7995\u7996\u7997\u7998\u7999\u799a\u799b\u799c\u799d\u799e\u799f\u79a0\u79a1\u79a2\u79a3\u79a4\u79a5\u79a6\u79a7\u79a8\u79a9\u79aa\u79ab\u79ac\u79ad\u79ae\u79af\u79b0\u79b1\u79b2\u79b3\u79b4\u79b5\u79b6\u79b7\u79b8\u79b9\u79ba\u79bb\u79bc\u79bd\u79be\u79bf\u79c0\u79c1\u79c2\u79c3\u79c4\u79c5\u79c6\u79c7\u79c8\u79c9\u79ca\u79cb\u79cc\u79cd\u79ce\u79cf\u79d0\u79d1\u79d2\u79d3\u79d4\u79d5\u79d6\u79d7\u79d8\u79d9\u79da\u79db\u79dc\u79dd\u79de\u79df\u79e0\u79e1\u79e2\u79e3\u79e4\u79e5\u79e6\u79e7\u79e8\u79e9\u79ea\u79eb\u79ec\u79ed\u79ee\u79ef\u79f0\u79f1\u79f2\u79f3\u79f4\u79f5\u79f6\u79f7\u79f8\u79f9\u79fa\u79fb\u79fc\u79fd\u79fe\u79ff\u7a00\u7a01\u7a02\u7a03\u7a04\u7a05\u7a06\u7a07\u7a08\u7a09\u7a0a\u7a0b\u7a0c\u7a0d\u7a0e\u7a0f\u7a10\u7a11\u7a12\u7a13\u7a14\u7a15\u7a16\u7a17\u7a18\u7a19\u7a1a\u7a1b\u7a1c\u7a1d\u7a1e\u7a1f\u7a20\u7a21\u7a22\u7a23\u7a24\u7a25\u7a26\u7a27\u7a28\u7a29\u7a2a\u7a2b\u7a2c\u7a2d\u7a2e\u7a2f\u7a30\u7a31\u7a32\u7a33\u7a34\u7a35\u7a36\u7a37\u7a38\u7a39\u7a3a\u7a3b\u7a3c\u7a3d\u7a3e\u7a3f\u7a40\u7a41\u7a42\u7a43\u7a44\u7a45\u7a46\u7a47\u7a48\u7a49\u7a4a\u7a4b\u7a4c\u7a4d\u7a4e\u7a4f\u7a50\u7a51\u7a52\u7a53\u7a54\u7a55\u7a56\u7a57\u7a58\u7a59\u7a5a\u7a5b\u7a5c\u7a5d\u7a5e\u7a5f\u7a60\u7a61\u7a62\u7a63\u7a64\u7a65\u7a66\u7a67\u7a68\u7a69\u7a6a\u7a6b\u7a6c\u7a6d\u7a6e\u7a6f\u7a70\u7a71\u7a72\u7a73\u7a74\u7a75\u7a76\u7a77\u7a78\u7a79\u7a7a\u7a7b\u7a7c\u7a7d\u7a7e\u7a7f\u7a80\u7a81\u7a82\u7a83\u7a84\u7a85\u7a86\u7a87\u7a88\u7a89\u7a8a\u7a8b\u7a8c\u7a8d\u7a8e\u7a8f\u7a90\u7a91\u7a92\u7a93\u7a94\u7a95\u7a96\u7a97\u7a98\u7a99\u7a9a\u7a9b\u7a9c\u7a9d\u7a9e\u7a9f\u7aa0\u7aa1\u7aa2\u7aa3\u7aa4\u7aa5\u7aa6\u7aa7\u7aa8\u7aa9\u7aaa\u7aab\u7aac\u7aad\u7aae\u7aaf\u7ab0\u7ab1\u7ab2\u7ab3\u7ab4\u7ab5\u7ab6\u7ab7\u7ab8\u7ab9\u7aba\u7abb\u7abc\u7abd\u7abe\u7abf\u7ac0\u7ac1\u7ac2\u7ac3\u7ac4\u7ac5\u7ac6\u7ac7\u7ac8\u7ac9\u7aca\u7acb\u7acc\u7acd\u7ace\u7acf\u7ad0\u7ad1\u7ad2\u7ad3\u7ad4\u7ad5\u7ad6\u7ad7\u7ad8\u7ad9\u7ada\u7adb\u7adc\u7add\u7ade\u7adf\u7ae0\u7ae1\u7ae2\u7ae3\u7ae4\u7ae5\u7ae6\u7ae7\u7ae8\u7ae9\u7aea\u7aeb\u7aec\u7aed\u7aee\u7aef\u7af0\u7af1\u7af2\u7af3\u7af4\u7af5\u7af6\u7af7\u7af8\u7af9\u7afa\u7afb\u7afc\u7afd\u7afe\u7aff\u7b00\u7b01\u7b02\u7b03\u7b04\u7b05\u7b06\u7b07\u7b08\u7b09\u7b0a\u7b0b\u7b0c\u7b0d\u7b0e\u7b0f\u7b10\u7b11\u7b12\u7b13\u7b14\u7b15\u7b16\u7b17\u7b18\u7b19\u7b1a\u7b1b\u7b1c\u7b1d\u7b1e\u7b1f\u7b20\u7b21\u7b22\u7b23\u7b24\u7b25\u7b26\u7b27\u7b28\u7b29\u7b2a\u7b2b\u7b2c\u7b2d\u7b2e\u7b2f\u7b30\u7b31\u7b32\u7b33\u7b34\u7b35\u7b36\u7b37\u7b38\u7b39\u7b3a\u7b3b\u7b3c\u7b3d\u7b3e\u7b3f\u7b40\u7b41\u7b42\u7b43\u7b44\u7b45\u7b46\u7b47\u7b48\u7b49\u7b4a\u7b4b\u7b4c\u7b4d\u7b4e\u7b4f\u7b50\u7b51\u7b52\u7b53\u7b54\u7b55\u7b56\u7b57\u7b58\u7b59\u7b5a\u7b5b\u7b5c\u7b5d\u7b5e\u7b5f\u7b60\u7b61\u7b62\u7b63\u7b64\u7b65\u7b66\u7b67\u7b68\u7b69\u7b6a\u7b6b\u7b6c\u7b6d\u7b6e\u7b6f\u7b70\u7b71\u7b72\u7b73\u7b74\u7b75\u7b76\u7b77\u7b78\u7b79\u7b7a\u7b7b\u7b7c\u7b7d\u7b7e\u7b7f\u7b80\u7b81\u7b82\u7b83\u7b84\u7b85\u7b86\u7b87\u7b88\u7b89\u7b8a\u7b8b\u7b8c\u7b8d\u7b8e\u7b8f\u7b90\u7b91\u7b92\u7b93\u7b94\u7b95\u7b96\u7b97\u7b98\u7b99\u7b9a\u7b9b\u7b9c\u7b9d\u7b9e\u7b9f\u7ba0\u7ba1\u7ba2\u7ba3\u7ba4\u7ba5\u7ba6\u7ba7\u7ba8\u7ba9\u7baa\u7bab\u7bac\u7bad\u7bae\u7baf\u7bb0\u7bb1\u7bb2\u7bb3\u7bb4\u7bb5\u7bb6\u7bb7\u7bb8\u7bb9\u7bba\u7bbb\u7bbc\u7bbd\u7bbe\u7bbf\u7bc0\u7bc1\u7bc2\u7bc3\u7bc4\u7bc5\u7bc6\u7bc7\u7bc8\u7bc9\u7bca\u7bcb\u7bcc\u7bcd\u7bce\u7bcf\u7bd0\u7bd1\u7bd2\u7bd3\u7bd4\u7bd5\u7bd6\u7bd7\u7bd8\u7bd9\u7bda\u7bdb\u7bdc\u7bdd\u7bde\u7bdf\u7be0\u7be1\u7be2\u7be3\u7be4\u7be5\u7be6\u7be7\u7be8\u7be9\u7bea\u7beb\u7bec\u7bed\u7bee\u7bef\u7bf0\u7bf1\u7bf2\u7bf3\u7bf4\u7bf5\u7bf6\u7bf7\u7bf8\u7bf9\u7bfa\u7bfb\u7bfc\u7bfd\u7bfe\u7bff\u7c00\u7c01\u7c02\u7c03\u7c04\u7c05\u7c06\u7c07\u7c08\u7c09\u7c0a\u7c0b\u7c0c\u7c0d\u7c0e\u7c0f\u7c10\u7c11\u7c12\u7c13\u7c14\u7c15\u7c16\u7c17\u7c18\u7c19\u7c1a\u7c1b\u7c1c\u7c1d\u7c1e\u7c1f\u7c20\u7c21\u7c22\u7c23\u7c24\u7c25\u7c26\u7c27\u7c28\u7c29\u7c2a\u7c2b\u7c2c\u7c2d\u7c2e\u7c2f\u7c30\u7c31\u7c32\u7c33\u7c34\u7c35\u7c36\u7c37\u7c38\u7c39\u7c3a\u7c3b\u7c3c\u7c3d\u7c3e\u7c3f\u7c40\u7c41\u7c42\u7c43\u7c44\u7c45\u7c46\u7c47\u7c48\u7c49\u7c4a\u7c4b\u7c4c\u7c4d\u7c4e\u7c4f\u7c50\u7c51\u7c52\u7c53\u7c54\u7c55\u7c56\u7c57\u7c58\u7c59\u7c5a\u7c5b\u7c5c\u7c5d\u7c5e\u7c5f\u7c60\u7c61\u7c62\u7c63\u7c64\u7c65\u7c66\u7c67\u7c68\u7c69\u7c6a\u7c6b\u7c6c\u7c6d\u7c6e\u7c6f\u7c70\u7c71\u7c72\u7c73\u7c74\u7c75\u7c76\u7c77\u7c78\u7c79\u7c7a\u7c7b\u7c7c\u7c7d\u7c7e\u7c7f\u7c80\u7c81\u7c82\u7c83\u7c84\u7c85\u7c86\u7c87\u7c88\u7c89\u7c8a\u7c8b\u7c8c\u7c8d\u7c8e\u7c8f\u7c90\u7c91\u7c92\u7c93\u7c94\u7c95\u7c96\u7c97\u7c98\u7c99\u7c9a\u7c9b\u7c9c\u7c9d\u7c9e\u7c9f\u7ca0\u7ca1\u7ca2\u7ca3\u7ca4\u7ca5\u7ca6\u7ca7\u7ca8\u7ca9\u7caa\u7cab\u7cac\u7cad\u7cae\u7caf\u7cb0\u7cb1\u7cb2\u7cb3\u7cb4\u7cb5\u7cb6\u7cb7\u7cb8\u7cb9\u7cba\u7cbb\u7cbc\u7cbd\u7cbe\u7cbf\u7cc0\u7cc1\u7cc2\u7cc3\u7cc4\u7cc5\u7cc6\u7cc7\u7cc8\u7cc9\u7cca\u7ccb\u7ccc\u7ccd\u7cce\u7ccf\u7cd0\u7cd1\u7cd2\u7cd3\u7cd4\u7cd5\u7cd6\u7cd7\u7cd8\u7cd9\u7cda\u7cdb\u7cdc\u7cdd\u7cde\u7cdf\u7ce0\u7ce1\u7ce2\u7ce3\u7ce4\u7ce5\u7ce6\u7ce7\u7ce8\u7ce9\u7cea\u7ceb\u7cec\u7ced\u7cee\u7cef\u7cf0\u7cf1\u7cf2\u7cf3\u7cf4\u7cf5\u7cf6\u7cf7\u7cf8\u7cf9\u7cfa\u7cfb\u7cfc\u7cfd\u7cfe\u7cff\u7d00\u7d01\u7d02\u7d03\u7d04\u7d05\u7d06\u7d07\u7d08\u7d09\u7d0a\u7d0b\u7d0c\u7d0d\u7d0e\u7d0f\u7d10\u7d11\u7d12\u7d13\u7d14\u7d15\u7d16\u7d17\u7d18\u7d19\u7d1a\u7d1b\u7d1c\u7d1d\u7d1e\u7d1f\u7d20\u7d21\u7d22\u7d23\u7d24\u7d25\u7d26\u7d27\u7d28\u7d29\u7d2a\u7d2b\u7d2c\u7d2d\u7d2e\u7d2f\u7d30\u7d31\u7d32\u7d33\u7d34\u7d35\u7d36\u7d37\u7d38\u7d39\u7d3a\u7d3b\u7d3c\u7d3d\u7d3e\u7d3f\u7d40\u7d41\u7d42\u7d43\u7d44\u7d45\u7d46\u7d47\u7d48\u7d49\u7d4a\u7d4b\u7d4c\u7d4d\u7d4e\u7d4f\u7d50\u7d51\u7d52\u7d53\u7d54\u7d55\u7d56\u7d57\u7d58\u7d59\u7d5a\u7d5b\u7d5c\u7d5d\u7d5e\u7d5f\u7d60\u7d61\u7d62\u7d63\u7d64\u7d65\u7d66\u7d67\u7d68\u7d69\u7d6a\u7d6b\u7d6c\u7d6d\u7d6e\u7d6f\u7d70\u7d71\u7d72\u7d73\u7d74\u7d75\u7d76\u7d77\u7d78\u7d79\u7d7a\u7d7b\u7d7c\u7d7d\u7d7e\u7d7f\u7d80\u7d81\u7d82\u7d83\u7d84\u7d85\u7d86\u7d87\u7d88\u7d89\u7d8a\u7d8b\u7d8c\u7d8d\u7d8e\u7d8f\u7d90\u7d91\u7d92\u7d93\u7d94\u7d95\u7d96\u7d97\u7d98\u7d99\u7d9a\u7d9b\u7d9c\u7d9d\u7d9e\u7d9f\u7da0\u7da1\u7da2\u7da3\u7da4\u7da5\u7da6\u7da7\u7da8\u7da9\u7daa\u7dab\u7dac\u7dad\u7dae\u7daf\u7db0\u7db1\u7db2\u7db3\u7db4\u7db5\u7db6\u7db7\u7db8\u7db9\u7dba\u7dbb\u7dbc\u7dbd\u7dbe\u7dbf\u7dc0\u7dc1\u7dc2\u7dc3\u7dc4\u7dc5\u7dc6\u7dc7\u7dc8\u7dc9\u7dca\u7dcb\u7dcc\u7dcd\u7dce\u7dcf\u7dd0\u7dd1\u7dd2\u7dd3\u7dd4\u7dd5\u7dd6\u7dd7\u7dd8\u7dd9\u7dda\u7ddb\u7ddc\u7ddd\u7dde\u7ddf\u7de0\u7de1\u7de2\u7de3\u7de4\u7de5\u7de6\u7de7\u7de8\u7de9\u7dea\u7deb\u7dec\u7ded\u7dee\u7def\u7df0\u7df1\u7df2\u7df3\u7df4\u7df5\u7df6\u7df7\u7df8\u7df9\u7dfa\u7dfb\u7dfc\u7dfd\u7dfe\u7dff\u7e00\u7e01\u7e02\u7e03\u7e04\u7e05\u7e06\u7e07\u7e08\u7e09\u7e0a\u7e0b\u7e0c\u7e0d\u7e0e\u7e0f\u7e10\u7e11\u7e12\u7e13\u7e14\u7e15\u7e16\u7e17\u7e18\u7e19\u7e1a\u7e1b\u7e1c\u7e1d\u7e1e\u7e1f\u7e20\u7e21\u7e22\u7e23\u7e24\u7e25\u7e26\u7e27\u7e28\u7e29\u7e2a\u7e2b\u7e2c\u7e2d\u7e2e\u7e2f\u7e30\u7e31\u7e32\u7e33\u7e34\u7e35\u7e36\u7e37\u7e38\u7e39\u7e3a\u7e3b\u7e3c\u7e3d\u7e3e\u7e3f\u7e40\u7e41\u7e42\u7e43\u7e44\u7e45\u7e46\u7e47\u7e48\u7e49\u7e4a\u7e4b\u7e4c\u7e4d\u7e4e\u7e4f\u7e50\u7e51\u7e52\u7e53\u7e54\u7e55\u7e56\u7e57\u7e58\u7e59\u7e5a\u7e5b\u7e5c\u7e5d\u7e5e\u7e5f\u7e60\u7e61\u7e62\u7e63\u7e64\u7e65\u7e66\u7e67\u7e68\u7e69\u7e6a\u7e6b\u7e6c\u7e6d\u7e6e\u7e6f\u7e70\u7e71\u7e72\u7e73\u7e74\u7e75\u7e76\u7e77\u7e78\u7e79\u7e7a\u7e7b\u7e7c\u7e7d\u7e7e\u7e7f\u7e80\u7e81\u7e82\u7e83\u7e84\u7e85\u7e86\u7e87\u7e88\u7e89\u7e8a\u7e8b\u7e8c\u7e8d\u7e8e\u7e8f\u7e90\u7e91\u7e92\u7e93\u7e94\u7e95\u7e96\u7e97\u7e98\u7e99\u7e9a\u7e9b\u7e9c\u7e9d\u7e9e\u7e9f\u7ea0\u7ea1\u7ea2\u7ea3\u7ea4\u7ea5\u7ea6\u7ea7\u7ea8\u7ea9\u7eaa\u7eab\u7eac\u7ead\u7eae\u7eaf\u7eb0\u7eb1\u7eb2\u7eb3\u7eb4\u7eb5\u7eb6\u7eb7\u7eb8\u7eb9\u7eba\u7ebb\u7ebc\u7ebd\u7ebe\u7ebf\u7ec0\u7ec1\u7ec2\u7ec3\u7ec4\u7ec5\u7ec6\u7ec7\u7ec8\u7ec9\u7eca\u7ecb\u7ecc\u7ecd\u7ece\u7ecf\u7ed0\u7ed1\u7ed2\u7ed3\u7ed4\u7ed5\u7ed6\u7ed7\u7ed8\u7ed9\u7eda\u7edb\u7edc\u7edd\u7ede\u7edf\u7ee0\u7ee1\u7ee2\u7ee3\u7ee4\u7ee5\u7ee6\u7ee7\u7ee8\u7ee9\u7eea\u7eeb\u7eec\u7eed\u7eee\u7eef\u7ef0\u7ef1\u7ef2\u7ef3\u7ef4\u7ef5\u7ef6\u7ef7\u7ef8\u7ef9\u7efa\u7efb\u7efc\u7efd\u7efe\u7eff\u7f00\u7f01\u7f02\u7f03\u7f04\u7f05\u7f06\u7f07\u7f08\u7f09\u7f0a\u7f0b\u7f0c\u7f0d\u7f0e\u7f0f\u7f10\u7f11\u7f12\u7f13\u7f14\u7f15\u7f16\u7f17\u7f18\u7f19\u7f1a\u7f1b\u7f1c\u7f1d\u7f1e\u7f1f\u7f20\u7f21\u7f22\u7f23\u7f24\u7f25\u7f26\u7f27\u7f28\u7f29\u7f2a\u7f2b\u7f2c\u7f2d\u7f2e\u7f2f\u7f30\u7f31\u7f32\u7f33\u7f34\u7f35\u7f36\u7f37\u7f38\u7f39\u7f3a\u7f3b\u7f3c\u7f3d\u7f3e\u7f3f\u7f40\u7f41\u7f42\u7f43\u7f44\u7f45\u7f46\u7f47\u7f48\u7f49\u7f4a\u7f4b\u7f4c\u7f4d\u7f4e\u7f4f\u7f50\u7f51\u7f52\u7f53\u7f54\u7f55\u7f56\u7f57\u7f58\u7f59\u7f5a\u7f5b\u7f5c\u7f5d\u7f5e\u7f5f\u7f60\u7f61\u7f62\u7f63\u7f64\u7f65\u7f66\u7f67\u7f68\u7f69\u7f6a\u7f6b\u7f6c\u7f6d\u7f6e\u7f6f\u7f70\u7f71\u7f72\u7f73\u7f74\u7f75\u7f76\u7f77\u7f78\u7f79\u7f7a\u7f7b\u7f7c\u7f7d\u7f7e\u7f7f\u7f80\u7f81\u7f82\u7f83\u7f84\u7f85\u7f86\u7f87\u7f88\u7f89\u7f8a\u7f8b\u7f8c\u7f8d\u7f8e\u7f8f\u7f90\u7f91\u7f92\u7f93\u7f94\u7f95\u7f96\u7f97\u7f98\u7f99\u7f9a\u7f9b\u7f9c\u7f9d\u7f9e\u7f9f\u7fa0\u7fa1\u7fa2\u7fa3\u7fa4\u7fa5\u7fa6\u7fa7\u7fa8\u7fa9\u7faa\u7fab\u7fac\u7fad\u7fae\u7faf\u7fb0\u7fb1\u7fb2\u7fb3\u7fb4\u7fb5\u7fb6\u7fb7\u7fb8\u7fb9\u7fba\u7fbb\u7fbc\u7fbd\u7fbe\u7fbf\u7fc0\u7fc1\u7fc2\u7fc3\u7fc4\u7fc5\u7fc6\u7fc7\u7fc8\u7fc9\u7fca\u7fcb\u7fcc\u7fcd\u7fce\u7fcf\u7fd0\u7fd1\u7fd2\u7fd3\u7fd4\u7fd5\u7fd6\u7fd7\u7fd8\u7fd9\u7fda\u7fdb\u7fdc\u7fdd\u7fde\u7fdf\u7fe0\u7fe1\u7fe2\u7fe3\u7fe4\u7fe5\u7fe6\u7fe7\u7fe8\u7fe9\u7fea\u7feb\u7fec\u7fed\u7fee\u7fef\u7ff0\u7ff1\u7ff2\u7ff3\u7ff4\u7ff5\u7ff6\u7ff7\u7ff8\u7ff9\u7ffa\u7ffb\u7ffc\u7ffd\u7ffe\u7fff\u8000\u8001\u8002\u8003\u8004\u8005\u8006\u8007\u8008\u8009\u800a\u800b\u800c\u800d\u800e\u800f\u8010\u8011\u8012\u8013\u8014\u8015\u8016\u8017\u8018\u8019\u801a\u801b\u801c\u801d\u801e\u801f\u8020\u8021\u8022\u8023\u8024\u8025\u8026\u8027\u8028\u8029\u802a\u802b\u802c\u802d\u802e\u802f\u8030\u8031\u8032\u8033\u8034\u8035\u8036\u8037\u8038\u8039\u803a\u803b\u803c\u803d\u803e\u803f\u8040\u8041\u8042\u8043\u8044\u8045\u8046\u8047\u8048\u8049\u804a\u804b\u804c\u804d\u804e\u804f\u8050\u8051\u8052\u8053\u8054\u8055\u8056\u8057\u8058\u8059\u805a\u805b\u805c\u805d\u805e\u805f\u8060\u8061\u8062\u8063\u8064\u8065\u8066\u8067\u8068\u8069\u806a\u806b\u806c\u806d\u806e\u806f\u8070\u8071\u8072\u8073\u8074\u8075\u8076\u8077\u8078\u8079\u807a\u807b\u807c\u807d\u807e\u807f\u8080\u8081\u8082\u8083\u8084\u8085\u8086\u8087\u8088\u8089\u808a\u808b\u808c\u808d\u808e\u808f\u8090\u8091\u8092\u8093\u8094\u8095\u8096\u8097\u8098\u8099\u809a\u809b\u809c\u809d\u809e\u809f\u80a0\u80a1\u80a2\u80a3\u80a4\u80a5\u80a6\u80a7\u80a8\u80a9\u80aa\u80ab\u80ac\u80ad\u80ae\u80af\u80b0\u80b1\u80b2\u80b3\u80b4\u80b5\u80b6\u80b7\u80b8\u80b9\u80ba\u80bb\u80bc\u80bd\u80be\u80bf\u80c0\u80c1\u80c2\u80c3\u80c4\u80c5\u80c6\u80c7\u80c8\u80c9\u80ca\u80cb\u80cc\u80cd\u80ce\u80cf\u80d0\u80d1\u80d2\u80d3\u80d4\u80d5\u80d6\u80d7\u80d8\u80d9\u80da\u80db\u80dc\u80dd\u80de\u80df\u80e0\u80e1\u80e2\u80e3\u80e4\u80e5\u80e6\u80e7\u80e8\u80e9\u80ea\u80eb\u80ec\u80ed\u80ee\u80ef\u80f0\u80f1\u80f2\u80f3\u80f4\u80f5\u80f6\u80f7\u80f8\u80f9\u80fa\u80fb\u80fc\u80fd\u80fe\u80ff\u8100\u8101\u8102\u8103\u8104\u8105\u8106\u8107\u8108\u8109\u810a\u810b\u810c\u810d\u810e\u810f\u8110\u8111\u8112\u8113\u8114\u8115\u8116\u8117\u8118\u8119\u811a\u811b\u811c\u811d\u811e\u811f\u8120\u8121\u8122\u8123\u8124\u8125\u8126\u8127\u8128\u8129\u812a\u812b\u812c\u812d\u812e\u812f\u8130\u8131\u8132\u8133\u8134\u8135\u8136\u8137\u8138\u8139\u813a\u813b\u813c\u813d\u813e\u813f\u8140\u8141\u8142\u8143\u8144\u8145\u8146\u8147\u8148\u8149\u814a\u814b\u814c\u814d\u814e\u814f\u8150\u8151\u8152\u8153\u8154\u8155\u8156\u8157\u8158\u8159\u815a\u815b\u815c\u815d\u815e\u815f\u8160\u8161\u8162\u8163\u8164\u8165\u8166\u8167\u8168\u8169\u816a\u816b\u816c\u816d\u816e\u816f\u8170\u8171\u8172\u8173\u8174\u8175\u8176\u8177\u8178\u8179\u817a\u817b\u817c\u817d\u817e\u817f\u8180\u8181\u8182\u8183\u8184\u8185\u8186\u8187\u8188\u8189\u818a\u818b\u818c\u818d\u818e\u818f\u8190\u8191\u8192\u8193\u8194\u8195\u8196\u8197\u8198\u8199\u819a\u819b\u819c\u819d\u819e\u819f\u81a0\u81a1\u81a2\u81a3\u81a4\u81a5\u81a6\u81a7\u81a8\u81a9\u81aa\u81ab\u81ac\u81ad\u81ae\u81af\u81b0\u81b1\u81b2\u81b3\u81b4\u81b5\u81b6\u81b7\u81b8\u81b9\u81ba\u81bb\u81bc\u81bd\u81be\u81bf\u81c0\u81c1\u81c2\u81c3\u81c4\u81c5\u81c6\u81c7\u81c8\u81c9\u81ca\u81cb\u81cc\u81cd\u81ce\u81cf\u81d0\u81d1\u81d2\u81d3\u81d4\u81d5\u81d6\u81d7\u81d8\u81d9\u81da\u81db\u81dc\u81dd\u81de\u81df\u81e0\u81e1\u81e2\u81e3\u81e4\u81e5\u81e6\u81e7\u81e8\u81e9\u81ea\u81eb\u81ec\u81ed\u81ee\u81ef\u81f0\u81f1\u81f2\u81f3\u81f4\u81f5\u81f6\u81f7\u81f8\u81f9\u81fa\u81fb\u81fc\u81fd\u81fe\u81ff\u8200\u8201\u8202\u8203\u8204\u8205\u8206\u8207\u8208\u8209\u820a\u820b\u820c\u820d\u820e\u820f\u8210\u8211\u8212\u8213\u8214\u8215\u8216\u8217\u8218\u8219\u821a\u821b\u821c\u821d\u821e\u821f\u8220\u8221\u8222\u8223\u8224\u8225\u8226\u8227\u8228\u8229\u822a\u822b\u822c\u822d\u822e\u822f\u8230\u8231\u8232\u8233\u8234\u8235\u8236\u8237\u8238\u8239\u823a\u823b\u823c\u823d\u823e\u823f\u8240\u8241\u8242\u8243\u8244\u8245\u8246\u8247\u8248\u8249\u824a\u824b\u824c\u824d\u824e\u824f\u8250\u8251\u8252\u8253\u8254\u8255\u8256\u8257\u8258\u8259\u825a\u825b\u825c\u825d\u825e\u825f\u8260\u8261\u8262\u8263\u8264\u8265\u8266\u8267\u8268\u8269\u826a\u826b\u826c\u826d\u826e\u826f\u8270\u8271\u8272\u8273\u8274\u8275\u8276\u8277\u8278\u8279\u827a\u827b\u827c\u827d\u827e\u827f\u8280\u8281\u8282\u8283\u8284\u8285\u8286\u8287\u8288\u8289\u828a\u828b\u828c\u828d\u828e\u828f\u8290\u8291\u8292\u8293\u8294\u8295\u8296\u8297\u8298\u8299\u829a\u829b\u829c\u829d\u829e\u829f\u82a0\u82a1\u82a2\u82a3\u82a4\u82a5\u82a6\u82a7\u82a8\u82a9\u82aa\u82ab\u82ac\u82ad\u82ae\u82af\u82b0\u82b1\u82b2\u82b3\u82b4\u82b5\u82b6\u82b7\u82b8\u82b9\u82ba\u82bb\u82bc\u82bd\u82be\u82bf\u82c0\u82c1\u82c2\u82c3\u82c4\u82c5\u82c6\u82c7\u82c8\u82c9\u82ca\u82cb\u82cc\u82cd\u82ce\u82cf\u82d0\u82d1\u82d2\u82d3\u82d4\u82d5\u82d6\u82d7\u82d8\u82d9\u82da\u82db\u82dc\u82dd\u82de\u82df\u82e0\u82e1\u82e2\u82e3\u82e4\u82e5\u82e6\u82e7\u82e8\u82e9\u82ea\u82eb\u82ec\u82ed\u82ee\u82ef\u82f0\u82f1\u82f2\u82f3\u82f4\u82f5\u82f6\u82f7\u82f8\u82f9\u82fa\u82fb\u82fc\u82fd\u82fe\u82ff\u8300\u8301\u8302\u8303\u8304\u8305\u8306\u8307\u8308\u8309\u830a\u830b\u830c\u830d\u830e\u830f\u8310\u8311\u8312\u8313\u8314\u8315\u8316\u8317\u8318\u8319\u831a\u831b\u831c\u831d\u831e\u831f\u8320\u8321\u8322\u8323\u8324\u8325\u8326\u8327\u8328\u8329\u832a\u832b\u832c\u832d\u832e\u832f\u8330\u8331\u8332\u8333\u8334\u8335\u8336\u8337\u8338\u8339\u833a\u833b\u833c\u833d\u833e\u833f\u8340\u8341\u8342\u8343\u8344\u8345\u8346\u8347\u8348\u8349\u834a\u834b\u834c\u834d\u834e\u834f\u8350\u8351\u8352\u8353\u8354\u8355\u8356\u8357\u8358\u8359\u835a\u835b\u835c\u835d\u835e\u835f\u8360\u8361\u8362\u8363\u8364\u8365\u8366\u8367\u8368\u8369\u836a\u836b\u836c\u836d\u836e\u836f\u8370\u8371\u8372\u8373\u8374\u8375\u8376\u8377\u8378\u8379\u837a\u837b\u837c\u837d\u837e\u837f\u8380\u8381\u8382\u8383\u8384\u8385\u8386\u8387\u8388\u8389\u838a\u838b\u838c\u838d\u838e\u838f\u8390\u8391\u8392\u8393\u8394\u8395\u8396\u8397\u8398\u8399\u839a\u839b\u839c\u839d\u839e\u839f\u83a0\u83a1\u83a2\u83a3\u83a4\u83a5\u83a6\u83a7\u83a8\u83a9\u83aa\u83ab\u83ac\u83ad\u83ae\u83af\u83b0\u83b1\u83b2\u83b3\u83b4\u83b5\u83b6\u83b7\u83b8\u83b9\u83ba\u83bb\u83bc\u83bd\u83be\u83bf\u83c0\u83c1\u83c2\u83c3\u83c4\u83c5\u83c6\u83c7\u83c8\u83c9\u83ca\u83cb\u83cc\u83cd\u83ce\u83cf\u83d0\u83d1\u83d2\u83d3\u83d4\u83d5\u83d6\u83d7\u83d8\u83d9\u83da\u83db\u83dc\u83dd\u83de\u83df\u83e0\u83e1\u83e2\u83e3\u83e4\u83e5\u83e6\u83e7\u83e8\u83e9\u83ea\u83eb\u83ec\u83ed\u83ee\u83ef\u83f0\u83f1\u83f2\u83f3\u83f4\u83f5\u83f6\u83f7\u83f8\u83f9\u83fa\u83fb\u83fc\u83fd\u83fe\u83ff\u8400\u8401\u8402\u8403\u8404\u8405\u8406\u8407\u8408\u8409\u840a\u840b\u840c\u840d\u840e\u840f\u8410\u8411\u8412\u8413\u8414\u8415\u8416\u8417\u8418\u8419\u841a\u841b\u841c\u841d\u841e\u841f\u8420\u8421\u8422\u8423\u8424\u8425\u8426\u8427\u8428\u8429\u842a\u842b\u842c\u842d\u842e\u842f\u8430\u8431\u8432\u8433\u8434\u8435\u8436\u8437\u8438\u8439\u843a\u843b\u843c\u843d\u843e\u843f\u8440\u8441\u8442\u8443\u8444\u8445\u8446\u8447\u8448\u8449\u844a\u844b\u844c\u844d\u844e\u844f\u8450\u8451\u8452\u8453\u8454\u8455\u8456\u8457\u8458\u8459\u845a\u845b\u845c\u845d\u845e\u845f\u8460\u8461\u8462\u8463\u8464\u8465\u8466\u8467\u8468\u8469\u846a\u846b\u846c\u846d\u846e\u846f\u8470\u8471\u8472\u8473\u8474\u8475\u8476\u8477\u8478\u8479\u847a\u847b\u847c\u847d\u847e\u847f\u8480\u8481\u8482\u8483\u8484\u8485\u8486\u8487\u8488\u8489\u848a\u848b\u848c\u848d\u848e\u848f\u8490\u8491\u8492\u8493\u8494\u8495\u8496\u8497\u8498\u8499\u849a\u849b\u849c\u849d\u849e\u849f\u84a0\u84a1\u84a2\u84a3\u84a4\u84a5\u84a6\u84a7\u84a8\u84a9\u84aa\u84ab\u84ac\u84ad\u84ae\u84af\u84b0\u84b1\u84b2\u84b3\u84b4\u84b5\u84b6\u84b7\u84b8\u84b9\u84ba\u84bb\u84bc\u84bd\u84be\u84bf\u84c0\u84c1\u84c2\u84c3\u84c4\u84c5\u84c6\u84c7\u84c8\u84c9\u84ca\u84cb\u84cc\u84cd\u84ce\u84cf\u84d0\u84d1\u84d2\u84d3\u84d4\u84d5\u84d6\u84d7\u84d8\u84d9\u84da\u84db\u84dc\u84dd\u84de\u84df\u84e0\u84e1\u84e2\u84e3\u84e4\u84e5\u84e6\u84e7\u84e8\u84e9\u84ea\u84eb\u84ec\u84ed\u84ee\u84ef\u84f0\u84f1\u84f2\u84f3\u84f4\u84f5\u84f6\u84f7\u84f8\u84f9\u84fa\u84fb\u84fc\u84fd\u84fe\u84ff\u8500\u8501\u8502\u8503\u8504\u8505\u8506\u8507\u8508\u8509\u850a\u850b\u850c\u850d\u850e\u850f\u8510\u8511\u8512\u8513\u8514\u8515\u8516\u8517\u8518\u8519\u851a\u851b\u851c\u851d\u851e\u851f\u8520\u8521\u8522\u8523\u8524\u8525\u8526\u8527\u8528\u8529\u852a\u852b\u852c\u852d\u852e\u852f\u8530\u8531\u8532\u8533\u8534\u8535\u8536\u8537\u8538\u8539\u853a\u853b\u853c\u853d\u853e\u853f\u8540\u8541\u8542\u8543\u8544\u8545\u8546\u8547\u8548\u8549\u854a\u854b\u854c\u854d\u854e\u854f\u8550\u8551\u8552\u8553\u8554\u8555\u8556\u8557\u8558\u8559\u855a\u855b\u855c\u855d\u855e\u855f\u8560\u8561\u8562\u8563\u8564\u8565\u8566\u8567\u8568\u8569\u856a\u856b\u856c\u856d\u856e\u856f\u8570\u8571\u8572\u8573\u8574\u8575\u8576\u8577\u8578\u8579\u857a\u857b\u857c\u857d\u857e\u857f\u8580\u8581\u8582\u8583\u8584\u8585\u8586\u8587\u8588\u8589\u858a\u858b\u858c\u858d\u858e\u858f\u8590\u8591\u8592\u8593\u8594\u8595\u8596\u8597\u8598\u8599\u859a\u859b\u859c\u859d\u859e\u859f\u85a0\u85a1\u85a2\u85a3\u85a4\u85a5\u85a6\u85a7\u85a8\u85a9\u85aa\u85ab\u85ac\u85ad\u85ae\u85af\u85b0\u85b1\u85b2\u85b3\u85b4\u85b5\u85b6\u85b7\u85b8\u85b9\u85ba\u85bb\u85bc\u85bd\u85be\u85bf\u85c0\u85c1\u85c2\u85c3\u85c4\u85c5\u85c6\u85c7\u85c8\u85c9\u85ca\u85cb\u85cc\u85cd\u85ce\u85cf\u85d0\u85d1\u85d2\u85d3\u85d4\u85d5\u85d6\u85d7\u85d8\u85d9\u85da\u85db\u85dc\u85dd\u85de\u85df\u85e0\u85e1\u85e2\u85e3\u85e4\u85e5\u85e6\u85e7\u85e8\u85e9\u85ea\u85eb\u85ec\u85ed\u85ee\u85ef\u85f0\u85f1\u85f2\u85f3\u85f4\u85f5\u85f6\u85f7\u85f8\u85f9\u85fa\u85fb\u85fc\u85fd\u85fe\u85ff\u8600\u8601\u8602\u8603\u8604\u8605\u8606\u8607\u8608\u8609\u860a\u860b\u860c\u860d\u860e\u860f\u8610\u8611\u8612\u8613\u8614\u8615\u8616\u8617\u8618\u8619\u861a\u861b\u861c\u861d\u861e\u861f\u8620\u8621\u8622\u8623\u8624\u8625\u8626\u8627\u8628\u8629\u862a\u862b\u862c\u862d\u862e\u862f\u8630\u8631\u8632\u8633\u8634\u8635\u8636\u8637\u8638\u8639\u863a\u863b\u863c\u863d\u863e\u863f\u8640\u8641\u8642\u8643\u8644\u8645\u8646\u8647\u8648\u8649\u864a\u864b\u864c\u864d\u864e\u864f\u8650\u8651\u8652\u8653\u8654\u8655\u8656\u8657\u8658\u8659\u865a\u865b\u865c\u865d\u865e\u865f\u8660\u8661\u8662\u8663\u8664\u8665\u8666\u8667\u8668\u8669\u866a\u866b\u866c\u866d\u866e\u866f\u8670\u8671\u8672\u8673\u8674\u8675\u8676\u8677\u8678\u8679\u867a\u867b\u867c\u867d\u867e\u867f\u8680\u8681\u8682\u8683\u8684\u8685\u8686\u8687\u8688\u8689\u868a\u868b\u868c\u868d\u868e\u868f\u8690\u8691\u8692\u8693\u8694\u8695\u8696\u8697\u8698\u8699\u869a\u869b\u869c\u869d\u869e\u869f\u86a0\u86a1\u86a2\u86a3\u86a4\u86a5\u86a6\u86a7\u86a8\u86a9\u86aa\u86ab\u86ac\u86ad\u86ae\u86af\u86b0\u86b1\u86b2\u86b3\u86b4\u86b5\u86b6\u86b7\u86b8\u86b9\u86ba\u86bb\u86bc\u86bd\u86be\u86bf\u86c0\u86c1\u86c2\u86c3\u86c4\u86c5\u86c6\u86c7\u86c8\u86c9\u86ca\u86cb\u86cc\u86cd\u86ce\u86cf\u86d0\u86d1\u86d2\u86d3\u86d4\u86d5\u86d6\u86d7\u86d8\u86d9\u86da\u86db\u86dc\u86dd\u86de\u86df\u86e0\u86e1\u86e2\u86e3\u86e4\u86e5\u86e6\u86e7\u86e8\u86e9\u86ea\u86eb\u86ec\u86ed\u86ee\u86ef\u86f0\u86f1\u86f2\u86f3\u86f4\u86f5\u86f6\u86f7\u86f8\u86f9\u86fa\u86fb\u86fc\u86fd\u86fe\u86ff\u8700\u8701\u8702\u8703\u8704\u8705\u8706\u8707\u8708\u8709\u870a\u870b\u870c\u870d\u870e\u870f\u8710\u8711\u8712\u8713\u8714\u8715\u8716\u8717\u8718\u8719\u871a\u871b\u871c\u871d\u871e\u871f\u8720\u8721\u8722\u8723\u8724\u8725\u8726\u8727\u8728\u8729\u872a\u872b\u872c\u872d\u872e\u872f\u8730\u8731\u8732\u8733\u8734\u8735\u8736\u8737\u8738\u8739\u873a\u873b\u873c\u873d\u873e\u873f\u8740\u8741\u8742\u8743\u8744\u8745\u8746\u8747\u8748\u8749\u874a\u874b\u874c\u874d\u874e\u874f\u8750\u8751\u8752\u8753\u8754\u8755\u8756\u8757\u8758\u8759\u875a\u875b\u875c\u875d\u875e\u875f\u8760\u8761\u8762\u8763\u8764\u8765\u8766\u8767\u8768\u8769\u876a\u876b\u876c\u876d\u876e\u876f\u8770\u8771\u8772\u8773\u8774\u8775\u8776\u8777\u8778\u8779\u877a\u877b\u877c\u877d\u877e\u877f\u8780\u8781\u8782\u8783\u8784\u8785\u8786\u8787\u8788\u8789\u878a\u878b\u878c\u878d\u878e\u878f\u8790\u8791\u8792\u8793\u8794\u8795\u8796\u8797\u8798\u8799\u879a\u879b\u879c\u879d\u879e\u879f\u87a0\u87a1\u87a2\u87a3\u87a4\u87a5\u87a6\u87a7\u87a8\u87a9\u87aa\u87ab\u87ac\u87ad\u87ae\u87af\u87b0\u87b1\u87b2\u87b3\u87b4\u87b5\u87b6\u87b7\u87b8\u87b9\u87ba\u87bb\u87bc\u87bd\u87be\u87bf\u87c0\u87c1\u87c2\u87c3\u87c4\u87c5\u87c6\u87c7\u87c8\u87c9\u87ca\u87cb\u87cc\u87cd\u87ce\u87cf\u87d0\u87d1\u87d2\u87d3\u87d4\u87d5\u87d6\u87d7\u87d8\u87d9\u87da\u87db\u87dc\u87dd\u87de\u87df\u87e0\u87e1\u87e2\u87e3\u87e4\u87e5\u87e6\u87e7\u87e8\u87e9\u87ea\u87eb\u87ec\u87ed\u87ee\u87ef\u87f0\u87f1\u87f2\u87f3\u87f4\u87f5\u87f6\u87f7\u87f8\u87f9\u87fa\u87fb\u87fc\u87fd\u87fe\u87ff\u8800\u8801\u8802\u8803\u8804\u8805\u8806\u8807\u8808\u8809\u880a\u880b\u880c\u880d\u880e\u880f\u8810\u8811\u8812\u8813\u8814\u8815\u8816\u8817\u8818\u8819\u881a\u881b\u881c\u881d\u881e\u881f\u8820\u8821\u8822\u8823\u8824\u8825\u8826\u8827\u8828\u8829\u882a\u882b\u882c\u882d\u882e\u882f\u8830\u8831\u8832\u8833\u8834\u8835\u8836\u8837\u8838\u8839\u883a\u883b\u883c\u883d\u883e\u883f\u8840\u8841\u8842\u8843\u8844\u8845\u8846\u8847\u8848\u8849\u884a\u884b\u884c\u884d\u884e\u884f\u8850\u8851\u8852\u8853\u8854\u8855\u8856\u8857\u8858\u8859\u885a\u885b\u885c\u885d\u885e\u885f\u8860\u8861\u8862\u8863\u8864\u8865\u8866\u8867\u8868\u8869\u886a\u886b\u886c\u886d\u886e\u886f\u8870\u8871\u8872\u8873\u8874\u8875\u8876\u8877\u8878\u8879\u887a\u887b\u887c\u887d\u887e\u887f\u8880\u8881\u8882\u8883\u8884\u8885\u8886\u8887\u8888\u8889\u888a\u888b\u888c\u888d\u888e\u888f\u8890\u8891\u8892\u8893\u8894\u8895\u8896\u8897\u8898\u8899\u889a\u889b\u889c\u889d\u889e\u889f\u88a0\u88a1\u88a2\u88a3\u88a4\u88a5\u88a6\u88a7\u88a8\u88a9\u88aa\u88ab\u88ac\u88ad\u88ae\u88af\u88b0\u88b1\u88b2\u88b3\u88b4\u88b5\u88b6\u88b7\u88b8\u88b9\u88ba\u88bb\u88bc\u88bd\u88be\u88bf\u88c0\u88c1\u88c2\u88c3\u88c4\u88c5\u88c6\u88c7\u88c8\u88c9\u88ca\u88cb\u88cc\u88cd\u88ce\u88cf\u88d0\u88d1\u88d2\u88d3\u88d4\u88d5\u88d6\u88d7\u88d8\u88d9\u88da\u88db\u88dc\u88dd\u88de\u88df\u88e0\u88e1\u88e2\u88e3\u88e4\u88e5\u88e6\u88e7\u88e8\u88e9\u88ea\u88eb\u88ec\u88ed\u88ee\u88ef\u88f0\u88f1\u88f2\u88f3\u88f4\u88f5\u88f6\u88f7\u88f8\u88f9\u88fa\u88fb\u88fc\u88fd\u88fe\u88ff\u8900\u8901\u8902\u8903\u8904\u8905\u8906\u8907\u8908\u8909\u890a\u890b\u890c\u890d\u890e\u890f\u8910\u8911\u8912\u8913\u8914\u8915\u8916\u8917\u8918\u8919\u891a\u891b\u891c\u891d\u891e\u891f\u8920\u8921\u8922\u8923\u8924\u8925\u8926\u8927\u8928\u8929\u892a\u892b\u892c\u892d\u892e\u892f\u8930\u8931\u8932\u8933\u8934\u8935\u8936\u8937\u8938\u8939\u893a\u893b\u893c\u893d\u893e\u893f\u8940\u8941\u8942\u8943\u8944\u8945\u8946\u8947\u8948\u8949\u894a\u894b\u894c\u894d\u894e\u894f\u8950\u8951\u8952\u8953\u8954\u8955\u8956\u8957\u8958\u8959\u895a\u895b\u895c\u895d\u895e\u895f\u8960\u8961\u8962\u8963\u8964\u8965\u8966\u8967\u8968\u8969\u896a\u896b\u896c\u896d\u896e\u896f\u8970\u8971\u8972\u8973\u8974\u8975\u8976\u8977\u8978\u8979\u897a\u897b\u897c\u897d\u897e\u897f\u8980\u8981\u8982\u8983\u8984\u8985\u8986\u8987\u8988\u8989\u898a\u898b\u898c\u898d\u898e\u898f\u8990\u8991\u8992\u8993\u8994\u8995\u8996\u8997\u8998\u8999\u899a\u899b\u899c\u899d\u899e\u899f\u89a0\u89a1\u89a2\u89a3\u89a4\u89a5\u89a6\u89a7\u89a8\u89a9\u89aa\u89ab\u89ac\u89ad\u89ae\u89af\u89b0\u89b1\u89b2\u89b3\u89b4\u89b5\u89b6\u89b7\u89b8\u89b9\u89ba\u89bb\u89bc\u89bd\u89be\u89bf\u89c0\u89c1\u89c2\u89c3\u89c4\u89c5\u89c6\u89c7\u89c8\u89c9\u89ca\u89cb\u89cc\u89cd\u89ce\u89cf\u89d0\u89d1\u89d2\u89d3\u89d4\u89d5\u89d6\u89d7\u89d8\u89d9\u89da\u89db\u89dc\u89dd\u89de\u89df\u89e0\u89e1\u89e2\u89e3\u89e4\u89e5\u89e6\u89e7\u89e8\u89e9\u89ea\u89eb\u89ec\u89ed\u89ee\u89ef\u89f0\u89f1\u89f2\u89f3\u89f4\u89f5\u89f6\u89f7\u89f8\u89f9\u89fa\u89fb\u89fc\u89fd\u89fe\u89ff\u8a00\u8a01\u8a02\u8a03\u8a04\u8a05\u8a06\u8a07\u8a08\u8a09\u8a0a\u8a0b\u8a0c\u8a0d\u8a0e\u8a0f\u8a10\u8a11\u8a12\u8a13\u8a14\u8a15\u8a16\u8a17\u8a18\u8a19\u8a1a\u8a1b\u8a1c\u8a1d\u8a1e\u8a1f\u8a20\u8a21\u8a22\u8a23\u8a24\u8a25\u8a26\u8a27\u8a28\u8a29\u8a2a\u8a2b\u8a2c\u8a2d\u8a2e\u8a2f\u8a30\u8a31\u8a32\u8a33\u8a34\u8a35\u8a36\u8a37\u8a38\u8a39\u8a3a\u8a3b\u8a3c\u8a3d\u8a3e\u8a3f\u8a40\u8a41\u8a42\u8a43\u8a44\u8a45\u8a46\u8a47\u8a48\u8a49\u8a4a\u8a4b\u8a4c\u8a4d\u8a4e\u8a4f\u8a50\u8a51\u8a52\u8a53\u8a54\u8a55\u8a56\u8a57\u8a58\u8a59\u8a5a\u8a5b\u8a5c\u8a5d\u8a5e\u8a5f\u8a60\u8a61\u8a62\u8a63\u8a64\u8a65\u8a66\u8a67\u8a68\u8a69\u8a6a\u8a6b\u8a6c\u8a6d\u8a6e\u8a6f\u8a70\u8a71\u8a72\u8a73\u8a74\u8a75\u8a76\u8a77\u8a78\u8a79\u8a7a\u8a7b\u8a7c\u8a7d\u8a7e\u8a7f\u8a80\u8a81\u8a82\u8a83\u8a84\u8a85\u8a86\u8a87\u8a88\u8a89\u8a8a\u8a8b\u8a8c\u8a8d\u8a8e\u8a8f\u8a90\u8a91\u8a92\u8a93\u8a94\u8a95\u8a96\u8a97\u8a98\u8a99\u8a9a\u8a9b\u8a9c\u8a9d\u8a9e\u8a9f\u8aa0\u8aa1\u8aa2\u8aa3\u8aa4\u8aa5\u8aa6\u8aa7\u8aa8\u8aa9\u8aaa\u8aab\u8aac\u8aad\u8aae\u8aaf\u8ab0\u8ab1\u8ab2\u8ab3\u8ab4\u8ab5\u8ab6\u8ab7\u8ab8\u8ab9\u8aba\u8abb\u8abc\u8abd\u8abe\u8abf\u8ac0\u8ac1\u8ac2\u8ac3\u8ac4\u8ac5\u8ac6\u8ac7\u8ac8\u8ac9\u8aca\u8acb\u8acc\u8acd\u8ace\u8acf\u8ad0\u8ad1\u8ad2\u8ad3\u8ad4\u8ad5\u8ad6\u8ad7\u8ad8\u8ad9\u8ada\u8adb\u8adc\u8add\u8ade\u8adf\u8ae0\u8ae1\u8ae2\u8ae3\u8ae4\u8ae5\u8ae6\u8ae7\u8ae8\u8ae9\u8aea\u8aeb\u8aec\u8aed\u8aee\u8aef\u8af0\u8af1\u8af2\u8af3\u8af4\u8af5\u8af6\u8af7\u8af8\u8af9\u8afa\u8afb\u8afc\u8afd\u8afe\u8aff\u8b00\u8b01\u8b02\u8b03\u8b04\u8b05\u8b06\u8b07\u8b08\u8b09\u8b0a\u8b0b\u8b0c\u8b0d\u8b0e\u8b0f\u8b10\u8b11\u8b12\u8b13\u8b14\u8b15\u8b16\u8b17\u8b18\u8b19\u8b1a\u8b1b\u8b1c\u8b1d\u8b1e\u8b1f\u8b20\u8b21\u8b22\u8b23\u8b24\u8b25\u8b26\u8b27\u8b28\u8b29\u8b2a\u8b2b\u8b2c\u8b2d\u8b2e\u8b2f\u8b30\u8b31\u8b32\u8b33\u8b34\u8b35\u8b36\u8b37\u8b38\u8b39\u8b3a\u8b3b\u8b3c\u8b3d\u8b3e\u8b3f\u8b40\u8b41\u8b42\u8b43\u8b44\u8b45\u8b46\u8b47\u8b48\u8b49\u8b4a\u8b4b\u8b4c\u8b4d\u8b4e\u8b4f\u8b50\u8b51\u8b52\u8b53\u8b54\u8b55\u8b56\u8b57\u8b58\u8b59\u8b5a\u8b5b\u8b5c\u8b5d\u8b5e\u8b5f\u8b60\u8b61\u8b62\u8b63\u8b64\u8b65\u8b66\u8b67\u8b68\u8b69\u8b6a\u8b6b\u8b6c\u8b6d\u8b6e\u8b6f\u8b70\u8b71\u8b72\u8b73\u8b74\u8b75\u8b76\u8b77\u8b78\u8b79\u8b7a\u8b7b\u8b7c\u8b7d\u8b7e\u8b7f\u8b80\u8b81\u8b82\u8b83\u8b84\u8b85\u8b86\u8b87\u8b88\u8b89\u8b8a\u8b8b\u8b8c\u8b8d\u8b8e\u8b8f\u8b90\u8b91\u8b92\u8b93\u8b94\u8b95\u8b96\u8b97\u8b98\u8b99\u8b9a\u8b9b\u8b9c\u8b9d\u8b9e\u8b9f\u8ba0\u8ba1\u8ba2\u8ba3\u8ba4\u8ba5\u8ba6\u8ba7\u8ba8\u8ba9\u8baa\u8bab\u8bac\u8bad\u8bae\u8baf\u8bb0\u8bb1\u8bb2\u8bb3\u8bb4\u8bb5\u8bb6\u8bb7\u8bb8\u8bb9\u8bba\u8bbb\u8bbc\u8bbd\u8bbe\u8bbf\u8bc0\u8bc1\u8bc2\u8bc3\u8bc4\u8bc5\u8bc6\u8bc7\u8bc8\u8bc9\u8bca\u8bcb\u8bcc\u8bcd\u8bce\u8bcf\u8bd0\u8bd1\u8bd2\u8bd3\u8bd4\u8bd5\u8bd6\u8bd7\u8bd8\u8bd9\u8bda\u8bdb\u8bdc\u8bdd\u8bde\u8bdf\u8be0\u8be1\u8be2\u8be3\u8be4\u8be5\u8be6\u8be7\u8be8\u8be9\u8bea\u8beb\u8bec\u8bed\u8bee\u8bef\u8bf0\u8bf1\u8bf2\u8bf3\u8bf4\u8bf5\u8bf6\u8bf7\u8bf8\u8bf9\u8bfa\u8bfb\u8bfc\u8bfd\u8bfe\u8bff\u8c00\u8c01\u8c02\u8c03\u8c04\u8c05\u8c06\u8c07\u8c08\u8c09\u8c0a\u8c0b\u8c0c\u8c0d\u8c0e\u8c0f\u8c10\u8c11\u8c12\u8c13\u8c14\u8c15\u8c16\u8c17\u8c18\u8c19\u8c1a\u8c1b\u8c1c\u8c1d\u8c1e\u8c1f\u8c20\u8c21\u8c22\u8c23\u8c24\u8c25\u8c26\u8c27\u8c28\u8c29\u8c2a\u8c2b\u8c2c\u8c2d\u8c2e\u8c2f\u8c30\u8c31\u8c32\u8c33\u8c34\u8c35\u8c36\u8c37\u8c38\u8c39\u8c3a\u8c3b\u8c3c\u8c3d\u8c3e\u8c3f\u8c40\u8c41\u8c42\u8c43\u8c44\u8c45\u8c46\u8c47\u8c48\u8c49\u8c4a\u8c4b\u8c4c\u8c4d\u8c4e\u8c4f\u8c50\u8c51\u8c52\u8c53\u8c54\u8c55\u8c56\u8c57\u8c58\u8c59\u8c5a\u8c5b\u8c5c\u8c5d\u8c5e\u8c5f\u8c60\u8c61\u8c62\u8c63\u8c64\u8c65\u8c66\u8c67\u8c68\u8c69\u8c6a\u8c6b\u8c6c\u8c6d\u8c6e\u8c6f\u8c70\u8c71\u8c72\u8c73\u8c74\u8c75\u8c76\u8c77\u8c78\u8c79\u8c7a\u8c7b\u8c7c\u8c7d\u8c7e\u8c7f\u8c80\u8c81\u8c82\u8c83\u8c84\u8c85\u8c86\u8c87\u8c88\u8c89\u8c8a\u8c8b\u8c8c\u8c8d\u8c8e\u8c8f\u8c90\u8c91\u8c92\u8c93\u8c94\u8c95\u8c96\u8c97\u8c98\u8c99\u8c9a\u8c9b\u8c9c\u8c9d\u8c9e\u8c9f\u8ca0\u8ca1\u8ca2\u8ca3\u8ca4\u8ca5\u8ca6\u8ca7\u8ca8\u8ca9\u8caa\u8cab\u8cac\u8cad\u8cae\u8caf\u8cb0\u8cb1\u8cb2\u8cb3\u8cb4\u8cb5\u8cb6\u8cb7\u8cb8\u8cb9\u8cba\u8cbb\u8cbc\u8cbd\u8cbe\u8cbf\u8cc0\u8cc1\u8cc2\u8cc3\u8cc4\u8cc5\u8cc6\u8cc7\u8cc8\u8cc9\u8cca\u8ccb\u8ccc\u8ccd\u8cce\u8ccf\u8cd0\u8cd1\u8cd2\u8cd3\u8cd4\u8cd5\u8cd6\u8cd7\u8cd8\u8cd9\u8cda\u8cdb\u8cdc\u8cdd\u8cde\u8cdf\u8ce0\u8ce1\u8ce2\u8ce3\u8ce4\u8ce5\u8ce6\u8ce7\u8ce8\u8ce9\u8cea\u8ceb\u8cec\u8ced\u8cee\u8cef\u8cf0\u8cf1\u8cf2\u8cf3\u8cf4\u8cf5\u8cf6\u8cf7\u8cf8\u8cf9\u8cfa\u8cfb\u8cfc\u8cfd\u8cfe\u8cff\u8d00\u8d01\u8d02\u8d03\u8d04\u8d05\u8d06\u8d07\u8d08\u8d09\u8d0a\u8d0b\u8d0c\u8d0d\u8d0e\u8d0f\u8d10\u8d11\u8d12\u8d13\u8d14\u8d15\u8d16\u8d17\u8d18\u8d19\u8d1a\u8d1b\u8d1c\u8d1d\u8d1e\u8d1f\u8d20\u8d21\u8d22\u8d23\u8d24\u8d25\u8d26\u8d27\u8d28\u8d29\u8d2a\u8d2b\u8d2c\u8d2d\u8d2e\u8d2f\u8d30\u8d31\u8d32\u8d33\u8d34\u8d35\u8d36\u8d37\u8d38\u8d39\u8d3a\u8d3b\u8d3c\u8d3d\u8d3e\u8d3f\u8d40\u8d41\u8d42\u8d43\u8d44\u8d45\u8d46\u8d47\u8d48\u8d49\u8d4a\u8d4b\u8d4c\u8d4d\u8d4e\u8d4f\u8d50\u8d51\u8d52\u8d53\u8d54\u8d55\u8d56\u8d57\u8d58\u8d59\u8d5a\u8d5b\u8d5c\u8d5d\u8d5e\u8d5f\u8d60\u8d61\u8d62\u8d63\u8d64\u8d65\u8d66\u8d67\u8d68\u8d69\u8d6a\u8d6b\u8d6c\u8d6d\u8d6e\u8d6f\u8d70\u8d71\u8d72\u8d73\u8d74\u8d75\u8d76\u8d77\u8d78\u8d79\u8d7a\u8d7b\u8d7c\u8d7d\u8d7e\u8d7f\u8d80\u8d81\u8d82\u8d83\u8d84\u8d85\u8d86\u8d87\u8d88\u8d89\u8d8a\u8d8b\u8d8c\u8d8d\u8d8e\u8d8f\u8d90\u8d91\u8d92\u8d93\u8d94\u8d95\u8d96\u8d97\u8d98\u8d99\u8d9a\u8d9b\u8d9c\u8d9d\u8d9e\u8d9f\u8da0\u8da1\u8da2\u8da3\u8da4\u8da5\u8da6\u8da7\u8da8\u8da9\u8daa\u8dab\u8dac\u8dad\u8dae\u8daf\u8db0\u8db1\u8db2\u8db3\u8db4\u8db5\u8db6\u8db7\u8db8\u8db9\u8dba\u8dbb\u8dbc\u8dbd\u8dbe\u8dbf\u8dc0\u8dc1\u8dc2\u8dc3\u8dc4\u8dc5\u8dc6\u8dc7\u8dc8\u8dc9\u8dca\u8dcb\u8dcc\u8dcd\u8dce\u8dcf\u8dd0\u8dd1\u8dd2\u8dd3\u8dd4\u8dd5\u8dd6\u8dd7\u8dd8\u8dd9\u8dda\u8ddb\u8ddc\u8ddd\u8dde\u8ddf\u8de0\u8de1\u8de2\u8de3\u8de4\u8de5\u8de6\u8de7\u8de8\u8de9\u8dea\u8deb\u8dec\u8ded\u8dee\u8def\u8df0\u8df1\u8df2\u8df3\u8df4\u8df5\u8df6\u8df7\u8df8\u8df9\u8dfa\u8dfb\u8dfc\u8dfd\u8dfe\u8dff\u8e00\u8e01\u8e02\u8e03\u8e04\u8e05\u8e06\u8e07\u8e08\u8e09\u8e0a\u8e0b\u8e0c\u8e0d\u8e0e\u8e0f\u8e10\u8e11\u8e12\u8e13\u8e14\u8e15\u8e16\u8e17\u8e18\u8e19\u8e1a\u8e1b\u8e1c\u8e1d\u8e1e\u8e1f\u8e20\u8e21\u8e22\u8e23\u8e24\u8e25\u8e26\u8e27\u8e28\u8e29\u8e2a\u8e2b\u8e2c\u8e2d\u8e2e\u8e2f\u8e30\u8e31\u8e32\u8e33\u8e34\u8e35\u8e36\u8e37\u8e38\u8e39\u8e3a\u8e3b\u8e3c\u8e3d\u8e3e\u8e3f\u8e40\u8e41\u8e42\u8e43\u8e44\u8e45\u8e46\u8e47\u8e48\u8e49\u8e4a\u8e4b\u8e4c\u8e4d\u8e4e\u8e4f\u8e50\u8e51\u8e52\u8e53\u8e54\u8e55\u8e56\u8e57\u8e58\u8e59\u8e5a\u8e5b\u8e5c\u8e5d\u8e5e\u8e5f\u8e60\u8e61\u8e62\u8e63\u8e64\u8e65\u8e66\u8e67\u8e68\u8e69\u8e6a\u8e6b\u8e6c\u8e6d\u8e6e\u8e6f\u8e70\u8e71\u8e72\u8e73\u8e74\u8e75\u8e76\u8e77\u8e78\u8e79\u8e7a\u8e7b\u8e7c\u8e7d\u8e7e\u8e7f\u8e80\u8e81\u8e82\u8e83\u8e84\u8e85\u8e86\u8e87\u8e88\u8e89\u8e8a\u8e8b\u8e8c\u8e8d\u8e8e\u8e8f\u8e90\u8e91\u8e92\u8e93\u8e94\u8e95\u8e96\u8e97\u8e98\u8e99\u8e9a\u8e9b\u8e9c\u8e9d\u8e9e\u8e9f\u8ea0\u8ea1\u8ea2\u8ea3\u8ea4\u8ea5\u8ea6\u8ea7\u8ea8\u8ea9\u8eaa\u8eab\u8eac\u8ead\u8eae\u8eaf\u8eb0\u8eb1\u8eb2\u8eb3\u8eb4\u8eb5\u8eb6\u8eb7\u8eb8\u8eb9\u8eba\u8ebb\u8ebc\u8ebd\u8ebe\u8ebf\u8ec0\u8ec1\u8ec2\u8ec3\u8ec4\u8ec5\u8ec6\u8ec7\u8ec8\u8ec9\u8eca\u8ecb\u8ecc\u8ecd\u8ece\u8ecf\u8ed0\u8ed1\u8ed2\u8ed3\u8ed4\u8ed5\u8ed6\u8ed7\u8ed8\u8ed9\u8eda\u8edb\u8edc\u8edd\u8ede\u8edf\u8ee0\u8ee1\u8ee2\u8ee3\u8ee4\u8ee5\u8ee6\u8ee7\u8ee8\u8ee9\u8eea\u8eeb\u8eec\u8eed\u8eee\u8eef\u8ef0\u8ef1\u8ef2\u8ef3\u8ef4\u8ef5\u8ef6\u8ef7\u8ef8\u8ef9\u8efa\u8efb\u8efc\u8efd\u8efe\u8eff\u8f00\u8f01\u8f02\u8f03\u8f04\u8f05\u8f06\u8f07\u8f08\u8f09\u8f0a\u8f0b\u8f0c\u8f0d\u8f0e\u8f0f\u8f10\u8f11\u8f12\u8f13\u8f14\u8f15\u8f16\u8f17\u8f18\u8f19\u8f1a\u8f1b\u8f1c\u8f1d\u8f1e\u8f1f\u8f20\u8f21\u8f22\u8f23\u8f24\u8f25\u8f26\u8f27\u8f28\u8f29\u8f2a\u8f2b\u8f2c\u8f2d\u8f2e\u8f2f\u8f30\u8f31\u8f32\u8f33\u8f34\u8f35\u8f36\u8f37\u8f38\u8f39\u8f3a\u8f3b\u8f3c\u8f3d\u8f3e\u8f3f\u8f40\u8f41\u8f42\u8f43\u8f44\u8f45\u8f46\u8f47\u8f48\u8f49\u8f4a\u8f4b\u8f4c\u8f4d\u8f4e\u8f4f\u8f50\u8f51\u8f52\u8f53\u8f54\u8f55\u8f56\u8f57\u8f58\u8f59\u8f5a\u8f5b\u8f5c\u8f5d\u8f5e\u8f5f\u8f60\u8f61\u8f62\u8f63\u8f64\u8f65\u8f66\u8f67\u8f68\u8f69\u8f6a\u8f6b\u8f6c\u8f6d\u8f6e\u8f6f\u8f70\u8f71\u8f72\u8f73\u8f74\u8f75\u8f76\u8f77\u8f78\u8f79\u8f7a\u8f7b\u8f7c\u8f7d\u8f7e\u8f7f\u8f80\u8f81\u8f82\u8f83\u8f84\u8f85\u8f86\u8f87\u8f88\u8f89\u8f8a\u8f8b\u8f8c\u8f8d\u8f8e\u8f8f\u8f90\u8f91\u8f92\u8f93\u8f94\u8f95\u8f96\u8f97\u8f98\u8f99\u8f9a\u8f9b\u8f9c\u8f9d\u8f9e\u8f9f\u8fa0\u8fa1\u8fa2\u8fa3\u8fa4\u8fa5\u8fa6\u8fa7\u8fa8\u8fa9\u8faa\u8fab\u8fac\u8fad\u8fae\u8faf\u8fb0\u8fb1\u8fb2\u8fb3\u8fb4\u8fb5\u8fb6\u8fb7\u8fb8\u8fb9\u8fba\u8fbb\u8fbc\u8fbd\u8fbe\u8fbf\u8fc0\u8fc1\u8fc2\u8fc3\u8fc4\u8fc5\u8fc6\u8fc7\u8fc8\u8fc9\u8fca\u8fcb\u8fcc\u8fcd\u8fce\u8fcf\u8fd0\u8fd1\u8fd2\u8fd3\u8fd4\u8fd5\u8fd6\u8fd7\u8fd8\u8fd9\u8fda\u8fdb\u8fdc\u8fdd\u8fde\u8fdf\u8fe0\u8fe1\u8fe2\u8fe3\u8fe4\u8fe5\u8fe6\u8fe7\u8fe8\u8fe9\u8fea\u8feb\u8fec\u8fed\u8fee\u8fef\u8ff0\u8ff1\u8ff2\u8ff3\u8ff4\u8ff5\u8ff6\u8ff7\u8ff8\u8ff9\u8ffa\u8ffb\u8ffc\u8ffd\u8ffe\u8fff\u9000\u9001\u9002\u9003\u9004\u9005\u9006\u9007\u9008\u9009\u900a\u900b\u900c\u900d\u900e\u900f\u9010\u9011\u9012\u9013\u9014\u9015\u9016\u9017\u9018\u9019\u901a\u901b\u901c\u901d\u901e\u901f\u9020\u9021\u9022\u9023\u9024\u9025\u9026\u9027\u9028\u9029\u902a\u902b\u902c\u902d\u902e\u902f\u9030\u9031\u9032\u9033\u9034\u9035\u9036\u9037\u9038\u9039\u903a\u903b\u903c\u903d\u903e\u903f\u9040\u9041\u9042\u9043\u9044\u9045\u9046\u9047\u9048\u9049\u904a\u904b\u904c\u904d\u904e\u904f\u9050\u9051\u9052\u9053\u9054\u9055\u9056\u9057\u9058\u9059\u905a\u905b\u905c\u905d\u905e\u905f\u9060\u9061\u9062\u9063\u9064\u9065\u9066\u9067\u9068\u9069\u906a\u906b\u906c\u906d\u906e\u906f\u9070\u9071\u9072\u9073\u9074\u9075\u9076\u9077\u9078\u9079\u907a\u907b\u907c\u907d\u907e\u907f\u9080\u9081\u9082\u9083\u9084\u9085\u9086\u9087\u9088\u9089\u908a\u908b\u908c\u908d\u908e\u908f\u9090\u9091\u9092\u9093\u9094\u9095\u9096\u9097\u9098\u9099\u909a\u909b\u909c\u909d\u909e\u909f\u90a0\u90a1\u90a2\u90a3\u90a4\u90a5\u90a6\u90a7\u90a8\u90a9\u90aa\u90ab\u90ac\u90ad\u90ae\u90af\u90b0\u90b1\u90b2\u90b3\u90b4\u90b5\u90b6\u90b7\u90b8\u90b9\u90ba\u90bb\u90bc\u90bd\u90be\u90bf\u90c0\u90c1\u90c2\u90c3\u90c4\u90c5\u90c6\u90c7\u90c8\u90c9\u90ca\u90cb\u90cc\u90cd\u90ce\u90cf\u90d0\u90d1\u90d2\u90d3\u90d4\u90d5\u90d6\u90d7\u90d8\u90d9\u90da\u90db\u90dc\u90dd\u90de\u90df\u90e0\u90e1\u90e2\u90e3\u90e4\u90e5\u90e6\u90e7\u90e8\u90e9\u90ea\u90eb\u90ec\u90ed\u90ee\u90ef\u90f0\u90f1\u90f2\u90f3\u90f4\u90f5\u90f6\u90f7\u90f8\u90f9\u90fa\u90fb\u90fc\u90fd\u90fe\u90ff\u9100\u9101\u9102\u9103\u9104\u9105\u9106\u9107\u9108\u9109\u910a\u910b\u910c\u910d\u910e\u910f\u9110\u9111\u9112\u9113\u9114\u9115\u9116\u9117\u9118\u9119\u911a\u911b\u911c\u911d\u911e\u911f\u9120\u9121\u9122\u9123\u9124\u9125\u9126\u9127\u9128\u9129\u912a\u912b\u912c\u912d\u912e\u912f\u9130\u9131\u9132\u9133\u9134\u9135\u9136\u9137\u9138\u9139\u913a\u913b\u913c\u913d\u913e\u913f\u9140\u9141\u9142\u9143\u9144\u9145\u9146\u9147\u9148\u9149\u914a\u914b\u914c\u914d\u914e\u914f\u9150\u9151\u9152\u9153\u9154\u9155\u9156\u9157\u9158\u9159\u915a\u915b\u915c\u915d\u915e\u915f\u9160\u9161\u9162\u9163\u9164\u9165\u9166\u9167\u9168\u9169\u916a\u916b\u916c\u916d\u916e\u916f\u9170\u9171\u9172\u9173\u9174\u9175\u9176\u9177\u9178\u9179\u917a\u917b\u917c\u917d\u917e\u917f\u9180\u9181\u9182\u9183\u9184\u9185\u9186\u9187\u9188\u9189\u918a\u918b\u918c\u918d\u918e\u918f\u9190\u9191\u9192\u9193\u9194\u9195\u9196\u9197\u9198\u9199\u919a\u919b\u919c\u919d\u919e\u919f\u91a0\u91a1\u91a2\u91a3\u91a4\u91a5\u91a6\u91a7\u91a8\u91a9\u91aa\u91ab\u91ac\u91ad\u91ae\u91af\u91b0\u91b1\u91b2\u91b3\u91b4\u91b5\u91b6\u91b7\u91b8\u91b9\u91ba\u91bb\u91bc\u91bd\u91be\u91bf\u91c0\u91c1\u91c2\u91c3\u91c4\u91c5\u91c6\u91c7\u91c8\u91c9\u91ca\u91cb\u91cc\u91cd\u91ce\u91cf\u91d0\u91d1\u91d2\u91d3\u91d4\u91d5\u91d6\u91d7\u91d8\u91d9\u91da\u91db\u91dc\u91dd\u91de\u91df\u91e0\u91e1\u91e2\u91e3\u91e4\u91e5\u91e6\u91e7\u91e8\u91e9\u91ea\u91eb\u91ec\u91ed\u91ee\u91ef\u91f0\u91f1\u91f2\u91f3\u91f4\u91f5\u91f6\u91f7\u91f8\u91f9\u91fa\u91fb\u91fc\u91fd\u91fe\u91ff\u9200\u9201\u9202\u9203\u9204\u9205\u9206\u9207\u9208\u9209\u920a\u920b\u920c\u920d\u920e\u920f\u9210\u9211\u9212\u9213\u9214\u9215\u9216\u9217\u9218\u9219\u921a\u921b\u921c\u921d\u921e\u921f\u9220\u9221\u9222\u9223\u9224\u9225\u9226\u9227\u9228\u9229\u922a\u922b\u922c\u922d\u922e\u922f\u9230\u9231\u9232\u9233\u9234\u9235\u9236\u9237\u9238\u9239\u923a\u923b\u923c\u923d\u923e\u923f\u9240\u9241\u9242\u9243\u9244\u9245\u9246\u9247\u9248\u9249\u924a\u924b\u924c\u924d\u924e\u924f\u9250\u9251\u9252\u9253\u9254\u9255\u9256\u9257\u9258\u9259\u925a\u925b\u925c\u925d\u925e\u925f\u9260\u9261\u9262\u9263\u9264\u9265\u9266\u9267\u9268\u9269\u926a\u926b\u926c\u926d\u926e\u926f\u9270\u9271\u9272\u9273\u9274\u9275\u9276\u9277\u9278\u9279\u927a\u927b\u927c\u927d\u927e\u927f\u9280\u9281\u9282\u9283\u9284\u9285\u9286\u9287\u9288\u9289\u928a\u928b\u928c\u928d\u928e\u928f\u9290\u9291\u9292\u9293\u9294\u9295\u9296\u9297\u9298\u9299\u929a\u929b\u929c\u929d\u929e\u929f\u92a0\u92a1\u92a2\u92a3\u92a4\u92a5\u92a6\u92a7\u92a8\u92a9\u92aa\u92ab\u92ac\u92ad\u92ae\u92af\u92b0\u92b1\u92b2\u92b3\u92b4\u92b5\u92b6\u92b7\u92b8\u92b9\u92ba\u92bb\u92bc\u92bd\u92be\u92bf\u92c0\u92c1\u92c2\u92c3\u92c4\u92c5\u92c6\u92c7\u92c8\u92c9\u92ca\u92cb\u92cc\u92cd\u92ce\u92cf\u92d0\u92d1\u92d2\u92d3\u92d4\u92d5\u92d6\u92d7\u92d8\u92d9\u92da\u92db\u92dc\u92dd\u92de\u92df\u92e0\u92e1\u92e2\u92e3\u92e4\u92e5\u92e6\u92e7\u92e8\u92e9\u92ea\u92eb\u92ec\u92ed\u92ee\u92ef\u92f0\u92f1\u92f2\u92f3\u92f4\u92f5\u92f6\u92f7\u92f8\u92f9\u92fa\u92fb\u92fc\u92fd\u92fe\u92ff\u9300\u9301\u9302\u9303\u9304\u9305\u9306\u9307\u9308\u9309\u930a\u930b\u930c\u930d\u930e\u930f\u9310\u9311\u9312\u9313\u9314\u9315\u9316\u9317\u9318\u9319\u931a\u931b\u931c\u931d\u931e\u931f\u9320\u9321\u9322\u9323\u9324\u9325\u9326\u9327\u9328\u9329\u932a\u932b\u932c\u932d\u932e\u932f\u9330\u9331\u9332\u9333\u9334\u9335\u9336\u9337\u9338\u9339\u933a\u933b\u933c\u933d\u933e\u933f\u9340\u9341\u9342\u9343\u9344\u9345\u9346\u9347\u9348\u9349\u934a\u934b\u934c\u934d\u934e\u934f\u9350\u9351\u9352\u9353\u9354\u9355\u9356\u9357\u9358\u9359\u935a\u935b\u935c\u935d\u935e\u935f\u9360\u9361\u9362\u9363\u9364\u9365\u9366\u9367\u9368\u9369\u936a\u936b\u936c\u936d\u936e\u936f\u9370\u9371\u9372\u9373\u9374\u9375\u9376\u9377\u9378\u9379\u937a\u937b\u937c\u937d\u937e\u937f\u9380\u9381\u9382\u9383\u9384\u9385\u9386\u9387\u9388\u9389\u938a\u938b\u938c\u938d\u938e\u938f\u9390\u9391\u9392\u9393\u9394\u9395\u9396\u9397\u9398\u9399\u939a\u939b\u939c\u939d\u939e\u939f\u93a0\u93a1\u93a2\u93a3\u93a4\u93a5\u93a6\u93a7\u93a8\u93a9\u93aa\u93ab\u93ac\u93ad\u93ae\u93af\u93b0\u93b1\u93b2\u93b3\u93b4\u93b5\u93b6\u93b7\u93b8\u93b9\u93ba\u93bb\u93bc\u93bd\u93be\u93bf\u93c0\u93c1\u93c2\u93c3\u93c4\u93c5\u93c6\u93c7\u93c8\u93c9\u93ca\u93cb\u93cc\u93cd\u93ce\u93cf\u93d0\u93d1\u93d2\u93d3\u93d4\u93d5\u93d6\u93d7\u93d8\u93d9\u93da\u93db\u93dc\u93dd\u93de\u93df\u93e0\u93e1\u93e2\u93e3\u93e4\u93e5\u93e6\u93e7\u93e8\u93e9\u93ea\u93eb\u93ec\u93ed\u93ee\u93ef\u93f0\u93f1\u93f2\u93f3\u93f4\u93f5\u93f6\u93f7\u93f8\u93f9\u93fa\u93fb\u93fc\u93fd\u93fe\u93ff\u9400\u9401\u9402\u9403\u9404\u9405\u9406\u9407\u9408\u9409\u940a\u940b\u940c\u940d\u940e\u940f\u9410\u9411\u9412\u9413\u9414\u9415\u9416\u9417\u9418\u9419\u941a\u941b\u941c\u941d\u941e\u941f\u9420\u9421\u9422\u9423\u9424\u9425\u9426\u9427\u9428\u9429\u942a\u942b\u942c\u942d\u942e\u942f\u9430\u9431\u9432\u9433\u9434\u9435\u9436\u9437\u9438\u9439\u943a\u943b\u943c\u943d\u943e\u943f\u9440\u9441\u9442\u9443\u9444\u9445\u9446\u9447\u9448\u9449\u944a\u944b\u944c\u944d\u944e\u944f\u9450\u9451\u9452\u9453\u9454\u9455\u9456\u9457\u9458\u9459\u945a\u945b\u945c\u945d\u945e\u945f\u9460\u9461\u9462\u9463\u9464\u9465\u9466\u9467\u9468\u9469\u946a\u946b\u946c\u946d\u946e\u946f\u9470\u9471\u9472\u9473\u9474\u9475\u9476\u9477\u9478\u9479\u947a\u947b\u947c\u947d\u947e\u947f\u9480\u9481\u9482\u9483\u9484\u9485\u9486\u9487\u9488\u9489\u948a\u948b\u948c\u948d\u948e\u948f\u9490\u9491\u9492\u9493\u9494\u9495\u9496\u9497\u9498\u9499\u949a\u949b\u949c\u949d\u949e\u949f\u94a0\u94a1\u94a2\u94a3\u94a4\u94a5\u94a6\u94a7\u94a8\u94a9\u94aa\u94ab\u94ac\u94ad\u94ae\u94af\u94b0\u94b1\u94b2\u94b3\u94b4\u94b5\u94b6\u94b7\u94b8\u94b9\u94ba\u94bb\u94bc\u94bd\u94be\u94bf\u94c0\u94c1\u94c2\u94c3\u94c4\u94c5\u94c6\u94c7\u94c8\u94c9\u94ca\u94cb\u94cc\u94cd\u94ce\u94cf\u94d0\u94d1\u94d2\u94d3\u94d4\u94d5\u94d6\u94d7\u94d8\u94d9\u94da\u94db\u94dc\u94dd\u94de\u94df\u94e0\u94e1\u94e2\u94e3\u94e4\u94e5\u94e6\u94e7\u94e8\u94e9\u94ea\u94eb\u94ec\u94ed\u94ee\u94ef\u94f0\u94f1\u94f2\u94f3\u94f4\u94f5\u94f6\u94f7\u94f8\u94f9\u94fa\u94fb\u94fc\u94fd\u94fe\u94ff\u9500\u9501\u9502\u9503\u9504\u9505\u9506\u9507\u9508\u9509\u950a\u950b\u950c\u950d\u950e\u950f\u9510\u9511\u9512\u9513\u9514\u9515\u9516\u9517\u9518\u9519\u951a\u951b\u951c\u951d\u951e\u951f\u9520\u9521\u9522\u9523\u9524\u9525\u9526\u9527\u9528\u9529\u952a\u952b\u952c\u952d\u952e\u952f\u9530\u9531\u9532\u9533\u9534\u9535\u9536\u9537\u9538\u9539\u953a\u953b\u953c\u953d\u953e\u953f\u9540\u9541\u9542\u9543\u9544\u9545\u9546\u9547\u9548\u9549\u954a\u954b\u954c\u954d\u954e\u954f\u9550\u9551\u9552\u9553\u9554\u9555\u9556\u9557\u9558\u9559\u955a\u955b\u955c\u955d\u955e\u955f\u9560\u9561\u9562\u9563\u9564\u9565\u9566\u9567\u9568\u9569\u956a\u956b\u956c\u956d\u956e\u956f\u9570\u9571\u9572\u9573\u9574\u9575\u9576\u9577\u9578\u9579\u957a\u957b\u957c\u957d\u957e\u957f\u9580\u9581\u9582\u9583\u9584\u9585\u9586\u9587\u9588\u9589\u958a\u958b\u958c\u958d\u958e\u958f\u9590\u9591\u9592\u9593\u9594\u9595\u9596\u9597\u9598\u9599\u959a\u959b\u959c\u959d\u959e\u959f\u95a0\u95a1\u95a2\u95a3\u95a4\u95a5\u95a6\u95a7\u95a8\u95a9\u95aa\u95ab\u95ac\u95ad\u95ae\u95af\u95b0\u95b1\u95b2\u95b3\u95b4\u95b5\u95b6\u95b7\u95b8\u95b9\u95ba\u95bb\u95bc\u95bd\u95be\u95bf\u95c0\u95c1\u95c2\u95c3\u95c4\u95c5\u95c6\u95c7\u95c8\u95c9\u95ca\u95cb\u95cc\u95cd\u95ce\u95cf\u95d0\u95d1\u95d2\u95d3\u95d4\u95d5\u95d6\u95d7\u95d8\u95d9\u95da\u95db\u95dc\u95dd\u95de\u95df\u95e0\u95e1\u95e2\u95e3\u95e4\u95e5\u95e6\u95e7\u95e8\u95e9\u95ea\u95eb\u95ec\u95ed\u95ee\u95ef\u95f0\u95f1\u95f2\u95f3\u95f4\u95f5\u95f6\u95f7\u95f8\u95f9\u95fa\u95fb\u95fc\u95fd\u95fe\u95ff\u9600\u9601\u9602\u9603\u9604\u9605\u9606\u9607\u9608\u9609\u960a\u960b\u960c\u960d\u960e\u960f\u9610\u9611\u9612\u9613\u9614\u9615\u9616\u9617\u9618\u9619\u961a\u961b\u961c\u961d\u961e\u961f\u9620\u9621\u9622\u9623\u9624\u9625\u9626\u9627\u9628\u9629\u962a\u962b\u962c\u962d\u962e\u962f\u9630\u9631\u9632\u9633\u9634\u9635\u9636\u9637\u9638\u9639\u963a\u963b\u963c\u963d\u963e\u963f\u9640\u9641\u9642\u9643\u9644\u9645\u9646\u9647\u9648\u9649\u964a\u964b\u964c\u964d\u964e\u964f\u9650\u9651\u9652\u9653\u9654\u9655\u9656\u9657\u9658\u9659\u965a\u965b\u965c\u965d\u965e\u965f\u9660\u9661\u9662\u9663\u9664\u9665\u9666\u9667\u9668\u9669\u966a\u966b\u966c\u966d\u966e\u966f\u9670\u9671\u9672\u9673\u9674\u9675\u9676\u9677\u9678\u9679\u967a\u967b\u967c\u967d\u967e\u967f\u9680\u9681\u9682\u9683\u9684\u9685\u9686\u9687\u9688\u9689\u968a\u968b\u968c\u968d\u968e\u968f\u9690\u9691\u9692\u9693\u9694\u9695\u9696\u9697\u9698\u9699\u969a\u969b\u969c\u969d\u969e\u969f\u96a0\u96a1\u96a2\u96a3\u96a4\u96a5\u96a6\u96a7\u96a8\u96a9\u96aa\u96ab\u96ac\u96ad\u96ae\u96af\u96b0\u96b1\u96b2\u96b3\u96b4\u96b5\u96b6\u96b7\u96b8\u96b9\u96ba\u96bb\u96bc\u96bd\u96be\u96bf\u96c0\u96c1\u96c2\u96c3\u96c4\u96c5\u96c6\u96c7\u96c8\u96c9\u96ca\u96cb\u96cc\u96cd\u96ce\u96cf\u96d0\u96d1\u96d2\u96d3\u96d4\u96d5\u96d6\u96d7\u96d8\u96d9\u96da\u96db\u96dc\u96dd\u96de\u96df\u96e0\u96e1\u96e2\u96e3\u96e4\u96e5\u96e6\u96e7\u96e8\u96e9\u96ea\u96eb\u96ec\u96ed\u96ee\u96ef\u96f0\u96f1\u96f2\u96f3\u96f4\u96f5\u96f6\u96f7\u96f8\u96f9\u96fa\u96fb\u96fc\u96fd\u96fe\u96ff\u9700\u9701\u9702\u9703\u9704\u9705\u9706\u9707\u9708\u9709\u970a\u970b\u970c\u970d\u970e\u970f\u9710\u9711\u9712\u9713\u9714\u9715\u9716\u9717\u9718\u9719\u971a\u971b\u971c\u971d\u971e\u971f\u9720\u9721\u9722\u9723\u9724\u9725\u9726\u9727\u9728\u9729\u972a\u972b\u972c\u972d\u972e\u972f\u9730\u9731\u9732\u9733\u9734\u9735\u9736\u9737\u9738\u9739\u973a\u973b\u973c\u973d\u973e\u973f\u9740\u9741\u9742\u9743\u9744\u9745\u9746\u9747\u9748\u9749\u974a\u974b\u974c\u974d\u974e\u974f\u9750\u9751\u9752\u9753\u9754\u9755\u9756\u9757\u9758\u9759\u975a\u975b\u975c\u975d\u975e\u975f\u9760\u9761\u9762\u9763\u9764\u9765\u9766\u9767\u9768\u9769\u976a\u976b\u976c\u976d\u976e\u976f\u9770\u9771\u9772\u9773\u9774\u9775\u9776\u9777\u9778\u9779\u977a\u977b\u977c\u977d\u977e\u977f\u9780\u9781\u9782\u9783\u9784\u9785\u9786\u9787\u9788\u9789\u978a\u978b\u978c\u978d\u978e\u978f\u9790\u9791\u9792\u9793\u9794\u9795\u9796\u9797\u9798\u9799\u979a\u979b\u979c\u979d\u979e\u979f\u97a0\u97a1\u97a2\u97a3\u97a4\u97a5\u97a6\u97a7\u97a8\u97a9\u97aa\u97ab\u97ac\u97ad\u97ae\u97af\u97b0\u97b1\u97b2\u97b3\u97b4\u97b5\u97b6\u97b7\u97b8\u97b9\u97ba\u97bb\u97bc\u97bd\u97be\u97bf\u97c0\u97c1\u97c2\u97c3\u97c4\u97c5\u97c6\u97c7\u97c8\u97c9\u97ca\u97cb\u97cc\u97cd\u97ce\u97cf\u97d0\u97d1\u97d2\u97d3\u97d4\u97d5\u97d6\u97d7\u97d8\u97d9\u97da\u97db\u97dc\u97dd\u97de\u97df\u97e0\u97e1\u97e2\u97e3\u97e4\u97e5\u97e6\u97e7\u97e8\u97e9\u97ea\u97eb\u97ec\u97ed\u97ee\u97ef\u97f0\u97f1\u97f2\u97f3\u97f4\u97f5\u97f6\u97f7\u97f8\u97f9\u97fa\u97fb\u97fc\u97fd\u97fe\u97ff\u9800\u9801\u9802\u9803\u9804\u9805\u9806\u9807\u9808\u9809\u980a\u980b\u980c\u980d\u980e\u980f\u9810\u9811\u9812\u9813\u9814\u9815\u9816\u9817\u9818\u9819\u981a\u981b\u981c\u981d\u981e\u981f\u9820\u9821\u9822\u9823\u9824\u9825\u9826\u9827\u9828\u9829\u982a\u982b\u982c\u982d\u982e\u982f\u9830\u9831\u9832\u9833\u9834\u9835\u9836\u9837\u9838\u9839\u983a\u983b\u983c\u983d\u983e\u983f\u9840\u9841\u9842\u9843\u9844\u9845\u9846\u9847\u9848\u9849\u984a\u984b\u984c\u984d\u984e\u984f\u9850\u9851\u9852\u9853\u9854\u9855\u9856\u9857\u9858\u9859\u985a\u985b\u985c\u985d\u985e\u985f\u9860\u9861\u9862\u9863\u9864\u9865\u9866\u9867\u9868\u9869\u986a\u986b\u986c\u986d\u986e\u986f\u9870\u9871\u9872\u9873\u9874\u9875\u9876\u9877\u9878\u9879\u987a\u987b\u987c\u987d\u987e\u987f\u9880\u9881\u9882\u9883\u9884\u9885\u9886\u9887\u9888\u9889\u988a\u988b\u988c\u988d\u988e\u988f\u9890\u9891\u9892\u9893\u9894\u9895\u9896\u9897\u9898\u9899\u989a\u989b\u989c\u989d\u989e\u989f\u98a0\u98a1\u98a2\u98a3\u98a4\u98a5\u98a6\u98a7\u98a8\u98a9\u98aa\u98ab\u98ac\u98ad\u98ae\u98af\u98b0\u98b1\u98b2\u98b3\u98b4\u98b5\u98b6\u98b7\u98b8\u98b9\u98ba\u98bb\u98bc\u98bd\u98be\u98bf\u98c0\u98c1\u98c2\u98c3\u98c4\u98c5\u98c6\u98c7\u98c8\u98c9\u98ca\u98cb\u98cc\u98cd\u98ce\u98cf\u98d0\u98d1\u98d2\u98d3\u98d4\u98d5\u98d6\u98d7\u98d8\u98d9\u98da\u98db\u98dc\u98dd\u98de\u98df\u98e0\u98e1\u98e2\u98e3\u98e4\u98e5\u98e6\u98e7\u98e8\u98e9\u98ea\u98eb\u98ec\u98ed\u98ee\u98ef\u98f0\u98f1\u98f2\u98f3\u98f4\u98f5\u98f6\u98f7\u98f8\u98f9\u98fa\u98fb\u98fc\u98fd\u98fe\u98ff\u9900\u9901\u9902\u9903\u9904\u9905\u9906\u9907\u9908\u9909\u990a\u990b\u990c\u990d\u990e\u990f\u9910\u9911\u9912\u9913\u9914\u9915\u9916\u9917\u9918\u9919\u991a\u991b\u991c\u991d\u991e\u991f\u9920\u9921\u9922\u9923\u9924\u9925\u9926\u9927\u9928\u9929\u992a\u992b\u992c\u992d\u992e\u992f\u9930\u9931\u9932\u9933\u9934\u9935\u9936\u9937\u9938\u9939\u993a\u993b\u993c\u993d\u993e\u993f\u9940\u9941\u9942\u9943\u9944\u9945\u9946\u9947\u9948\u9949\u994a\u994b\u994c\u994d\u994e\u994f\u9950\u9951\u9952\u9953\u9954\u9955\u9956\u9957\u9958\u9959\u995a\u995b\u995c\u995d\u995e\u995f\u9960\u9961\u9962\u9963\u9964\u9965\u9966\u9967\u9968\u9969\u996a\u996b\u996c\u996d\u996e\u996f\u9970\u9971\u9972\u9973\u9974\u9975\u9976\u9977\u9978\u9979\u997a\u997b\u997c\u997d\u997e\u997f\u9980\u9981\u9982\u9983\u9984\u9985\u9986\u9987\u9988\u9989\u998a\u998b\u998c\u998d\u998e\u998f\u9990\u9991\u9992\u9993\u9994\u9995\u9996\u9997\u9998\u9999\u999a\u999b\u999c\u999d\u999e\u999f\u99a0\u99a1\u99a2\u99a3\u99a4\u99a5\u99a6\u99a7\u99a8\u99a9\u99aa\u99ab\u99ac\u99ad\u99ae\u99af\u99b0\u99b1\u99b2\u99b3\u99b4\u99b5\u99b6\u99b7\u99b8\u99b9\u99ba\u99bb\u99bc\u99bd\u99be\u99bf\u99c0\u99c1\u99c2\u99c3\u99c4\u99c5\u99c6\u99c7\u99c8\u99c9\u99ca\u99cb\u99cc\u99cd\u99ce\u99cf\u99d0\u99d1\u99d2\u99d3\u99d4\u99d5\u99d6\u99d7\u99d8\u99d9\u99da\u99db\u99dc\u99dd\u99de\u99df\u99e0\u99e1\u99e2\u99e3\u99e4\u99e5\u99e6\u99e7\u99e8\u99e9\u99ea\u99eb\u99ec\u99ed\u99ee\u99ef\u99f0\u99f1\u99f2\u99f3\u99f4\u99f5\u99f6\u99f7\u99f8\u99f9\u99fa\u99fb\u99fc\u99fd\u99fe\u99ff\u9a00\u9a01\u9a02\u9a03\u9a04\u9a05\u9a06\u9a07\u9a08\u9a09\u9a0a\u9a0b\u9a0c\u9a0d\u9a0e\u9a0f\u9a10\u9a11\u9a12\u9a13\u9a14\u9a15\u9a16\u9a17\u9a18\u9a19\u9a1a\u9a1b\u9a1c\u9a1d\u9a1e\u9a1f\u9a20\u9a21\u9a22\u9a23\u9a24\u9a25\u9a26\u9a27\u9a28\u9a29\u9a2a\u9a2b\u9a2c\u9a2d\u9a2e\u9a2f\u9a30\u9a31\u9a32\u9a33\u9a34\u9a35\u9a36\u9a37\u9a38\u9a39\u9a3a\u9a3b\u9a3c\u9a3d\u9a3e\u9a3f\u9a40\u9a41\u9a42\u9a43\u9a44\u9a45\u9a46\u9a47\u9a48\u9a49\u9a4a\u9a4b\u9a4c\u9a4d\u9a4e\u9a4f\u9a50\u9a51\u9a52\u9a53\u9a54\u9a55\u9a56\u9a57\u9a58\u9a59\u9a5a\u9a5b\u9a5c\u9a5d\u9a5e\u9a5f\u9a60\u9a61\u9a62\u9a63\u9a64\u9a65\u9a66\u9a67\u9a68\u9a69\u9a6a\u9a6b\u9a6c\u9a6d\u9a6e\u9a6f\u9a70\u9a71\u9a72\u9a73\u9a74\u9a75\u9a76\u9a77\u9a78\u9a79\u9a7a\u9a7b\u9a7c\u9a7d\u9a7e\u9a7f\u9a80\u9a81\u9a82\u9a83\u9a84\u9a85\u9a86\u9a87\u9a88\u9a89\u9a8a\u9a8b\u9a8c\u9a8d\u9a8e\u9a8f\u9a90\u9a91\u9a92\u9a93\u9a94\u9a95\u9a96\u9a97\u9a98\u9a99\u9a9a\u9a9b\u9a9c\u9a9d\u9a9e\u9a9f\u9aa0\u9aa1\u9aa2\u9aa3\u9aa4\u9aa5\u9aa6\u9aa7\u9aa8\u9aa9\u9aaa\u9aab\u9aac\u9aad\u9aae\u9aaf\u9ab0\u9ab1\u9ab2\u9ab3\u9ab4\u9ab5\u9ab6\u9ab7\u9ab8\u9ab9\u9aba\u9abb\u9abc\u9abd\u9abe\u9abf\u9ac0\u9ac1\u9ac2\u9ac3\u9ac4\u9ac5\u9ac6\u9ac7\u9ac8\u9ac9\u9aca\u9acb\u9acc\u9acd\u9ace\u9acf\u9ad0\u9ad1\u9ad2\u9ad3\u9ad4\u9ad5\u9ad6\u9ad7\u9ad8\u9ad9\u9ada\u9adb\u9adc\u9add\u9ade\u9adf\u9ae0\u9ae1\u9ae2\u9ae3\u9ae4\u9ae5\u9ae6\u9ae7\u9ae8\u9ae9\u9aea\u9aeb\u9aec\u9aed\u9aee\u9aef\u9af0\u9af1\u9af2\u9af3\u9af4\u9af5\u9af6\u9af7\u9af8\u9af9\u9afa\u9afb\u9afc\u9afd\u9afe\u9aff\u9b00\u9b01\u9b02\u9b03\u9b04\u9b05\u9b06\u9b07\u9b08\u9b09\u9b0a\u9b0b\u9b0c\u9b0d\u9b0e\u9b0f\u9b10\u9b11\u9b12\u9b13\u9b14\u9b15\u9b16\u9b17\u9b18\u9b19\u9b1a\u9b1b\u9b1c\u9b1d\u9b1e\u9b1f\u9b20\u9b21\u9b22\u9b23\u9b24\u9b25\u9b26\u9b27\u9b28\u9b29\u9b2a\u9b2b\u9b2c\u9b2d\u9b2e\u9b2f\u9b30\u9b31\u9b32\u9b33\u9b34\u9b35\u9b36\u9b37\u9b38\u9b39\u9b3a\u9b3b\u9b3c\u9b3d\u9b3e\u9b3f\u9b40\u9b41\u9b42\u9b43\u9b44\u9b45\u9b46\u9b47\u9b48\u9b49\u9b4a\u9b4b\u9b4c\u9b4d\u9b4e\u9b4f\u9b50\u9b51\u9b52\u9b53\u9b54\u9b55\u9b56\u9b57\u9b58\u9b59\u9b5a\u9b5b\u9b5c\u9b5d\u9b5e\u9b5f\u9b60\u9b61\u9b62\u9b63\u9b64\u9b65\u9b66\u9b67\u9b68\u9b69\u9b6a\u9b6b\u9b6c\u9b6d\u9b6e\u9b6f\u9b70\u9b71\u9b72\u9b73\u9b74\u9b75\u9b76\u9b77\u9b78\u9b79\u9b7a\u9b7b\u9b7c\u9b7d\u9b7e\u9b7f\u9b80\u9b81\u9b82\u9b83\u9b84\u9b85\u9b86\u9b87\u9b88\u9b89\u9b8a\u9b8b\u9b8c\u9b8d\u9b8e\u9b8f\u9b90\u9b91\u9b92\u9b93\u9b94\u9b95\u9b96\u9b97\u9b98\u9b99\u9b9a\u9b9b\u9b9c\u9b9d\u9b9e\u9b9f\u9ba0\u9ba1\u9ba2\u9ba3\u9ba4\u9ba5\u9ba6\u9ba7\u9ba8\u9ba9\u9baa\u9bab\u9bac\u9bad\u9bae\u9baf\u9bb0\u9bb1\u9bb2\u9bb3\u9bb4\u9bb5\u9bb6\u9bb7\u9bb8\u9bb9\u9bba\u9bbb\u9bbc\u9bbd\u9bbe\u9bbf\u9bc0\u9bc1\u9bc2\u9bc3\u9bc4\u9bc5\u9bc6\u9bc7\u9bc8\u9bc9\u9bca\u9bcb\u9bcc\u9bcd\u9bce\u9bcf\u9bd0\u9bd1\u9bd2\u9bd3\u9bd4\u9bd5\u9bd6\u9bd7\u9bd8\u9bd9\u9bda\u9bdb\u9bdc\u9bdd\u9bde\u9bdf\u9be0\u9be1\u9be2\u9be3\u9be4\u9be5\u9be6\u9be7\u9be8\u9be9\u9bea\u9beb\u9bec\u9bed\u9bee\u9bef\u9bf0\u9bf1\u9bf2\u9bf3\u9bf4\u9bf5\u9bf6\u9bf7\u9bf8\u9bf9\u9bfa\u9bfb\u9bfc\u9bfd\u9bfe\u9bff\u9c00\u9c01\u9c02\u9c03\u9c04\u9c05\u9c06\u9c07\u9c08\u9c09\u9c0a\u9c0b\u9c0c\u9c0d\u9c0e\u9c0f\u9c10\u9c11\u9c12\u9c13\u9c14\u9c15\u9c16\u9c17\u9c18\u9c19\u9c1a\u9c1b\u9c1c\u9c1d\u9c1e\u9c1f\u9c20\u9c21\u9c22\u9c23\u9c24\u9c25\u9c26\u9c27\u9c28\u9c29\u9c2a\u9c2b\u9c2c\u9c2d\u9c2e\u9c2f\u9c30\u9c31\u9c32\u9c33\u9c34\u9c35\u9c36\u9c37\u9c38\u9c39\u9c3a\u9c3b\u9c3c\u9c3d\u9c3e\u9c3f\u9c40\u9c41\u9c42\u9c43\u9c44\u9c45\u9c46\u9c47\u9c48\u9c49\u9c4a\u9c4b\u9c4c\u9c4d\u9c4e\u9c4f\u9c50\u9c51\u9c52\u9c53\u9c54\u9c55\u9c56\u9c57\u9c58\u9c59\u9c5a\u9c5b\u9c5c\u9c5d\u9c5e\u9c5f\u9c60\u9c61\u9c62\u9c63\u9c64\u9c65\u9c66\u9c67\u9c68\u9c69\u9c6a\u9c6b\u9c6c\u9c6d\u9c6e\u9c6f\u9c70\u9c71\u9c72\u9c73\u9c74\u9c75\u9c76\u9c77\u9c78\u9c79\u9c7a\u9c7b\u9c7c\u9c7d\u9c7e\u9c7f\u9c80\u9c81\u9c82\u9c83\u9c84\u9c85\u9c86\u9c87\u9c88\u9c89\u9c8a\u9c8b\u9c8c\u9c8d\u9c8e\u9c8f\u9c90\u9c91\u9c92\u9c93\u9c94\u9c95\u9c96\u9c97\u9c98\u9c99\u9c9a\u9c9b\u9c9c\u9c9d\u9c9e\u9c9f\u9ca0\u9ca1\u9ca2\u9ca3\u9ca4\u9ca5\u9ca6\u9ca7\u9ca8\u9ca9\u9caa\u9cab\u9cac\u9cad\u9cae\u9caf\u9cb0\u9cb1\u9cb2\u9cb3\u9cb4\u9cb5\u9cb6\u9cb7\u9cb8\u9cb9\u9cba\u9cbb\u9cbc\u9cbd\u9cbe\u9cbf\u9cc0\u9cc1\u9cc2\u9cc3\u9cc4\u9cc5\u9cc6\u9cc7\u9cc8\u9cc9\u9cca\u9ccb\u9ccc\u9ccd\u9cce\u9ccf\u9cd0\u9cd1\u9cd2\u9cd3\u9cd4\u9cd5\u9cd6\u9cd7\u9cd8\u9cd9\u9cda\u9cdb\u9cdc\u9cdd\u9cde\u9cdf\u9ce0\u9ce1\u9ce2\u9ce3\u9ce4\u9ce5\u9ce6\u9ce7\u9ce8\u9ce9\u9cea\u9ceb\u9cec\u9ced\u9cee\u9cef\u9cf0\u9cf1\u9cf2\u9cf3\u9cf4\u9cf5\u9cf6\u9cf7\u9cf8\u9cf9\u9cfa\u9cfb\u9cfc\u9cfd\u9cfe\u9cff\u9d00\u9d01\u9d02\u9d03\u9d04\u9d05\u9d06\u9d07\u9d08\u9d09\u9d0a\u9d0b\u9d0c\u9d0d\u9d0e\u9d0f\u9d10\u9d11\u9d12\u9d13\u9d14\u9d15\u9d16\u9d17\u9d18\u9d19\u9d1a\u9d1b\u9d1c\u9d1d\u9d1e\u9d1f\u9d20\u9d21\u9d22\u9d23\u9d24\u9d25\u9d26\u9d27\u9d28\u9d29\u9d2a\u9d2b\u9d2c\u9d2d\u9d2e\u9d2f\u9d30\u9d31\u9d32\u9d33\u9d34\u9d35\u9d36\u9d37\u9d38\u9d39\u9d3a\u9d3b\u9d3c\u9d3d\u9d3e\u9d3f\u9d40\u9d41\u9d42\u9d43\u9d44\u9d45\u9d46\u9d47\u9d48\u9d49\u9d4a\u9d4b\u9d4c\u9d4d\u9d4e\u9d4f\u9d50\u9d51\u9d52\u9d53\u9d54\u9d55\u9d56\u9d57\u9d58\u9d59\u9d5a\u9d5b\u9d5c\u9d5d\u9d5e\u9d5f\u9d60\u9d61\u9d62\u9d63\u9d64\u9d65\u9d66\u9d67\u9d68\u9d69\u9d6a\u9d6b\u9d6c\u9d6d\u9d6e\u9d6f\u9d70\u9d71\u9d72\u9d73\u9d74\u9d75\u9d76\u9d77\u9d78\u9d79\u9d7a\u9d7b\u9d7c\u9d7d\u9d7e\u9d7f\u9d80\u9d81\u9d82\u9d83\u9d84\u9d85\u9d86\u9d87\u9d88\u9d89\u9d8a\u9d8b\u9d8c\u9d8d\u9d8e\u9d8f\u9d90\u9d91\u9d92\u9d93\u9d94\u9d95\u9d96\u9d97\u9d98\u9d99\u9d9a\u9d9b\u9d9c\u9d9d\u9d9e\u9d9f\u9da0\u9da1\u9da2\u9da3\u9da4\u9da5\u9da6\u9da7\u9da8\u9da9\u9daa\u9dab\u9dac\u9dad\u9dae\u9daf\u9db0\u9db1\u9db2\u9db3\u9db4\u9db5\u9db6\u9db7\u9db8\u9db9\u9dba\u9dbb\u9dbc\u9dbd\u9dbe\u9dbf\u9dc0\u9dc1\u9dc2\u9dc3\u9dc4\u9dc5\u9dc6\u9dc7\u9dc8\u9dc9\u9dca\u9dcb\u9dcc\u9dcd\u9dce\u9dcf\u9dd0\u9dd1\u9dd2\u9dd3\u9dd4\u9dd5\u9dd6\u9dd7\u9dd8\u9dd9\u9dda\u9ddb\u9ddc\u9ddd\u9dde\u9ddf\u9de0\u9de1\u9de2\u9de3\u9de4\u9de5\u9de6\u9de7\u9de8\u9de9\u9dea\u9deb\u9dec\u9ded\u9dee\u9def\u9df0\u9df1\u9df2\u9df3\u9df4\u9df5\u9df6\u9df7\u9df8\u9df9\u9dfa\u9dfb\u9dfc\u9dfd\u9dfe\u9dff\u9e00\u9e01\u9e02\u9e03\u9e04\u9e05\u9e06\u9e07\u9e08\u9e09\u9e0a\u9e0b\u9e0c\u9e0d\u9e0e\u9e0f\u9e10\u9e11\u9e12\u9e13\u9e14\u9e15\u9e16\u9e17\u9e18\u9e19\u9e1a\u9e1b\u9e1c\u9e1d\u9e1e\u9e1f\u9e20\u9e21\u9e22\u9e23\u9e24\u9e25\u9e26\u9e27\u9e28\u9e29\u9e2a\u9e2b\u9e2c\u9e2d\u9e2e\u9e2f\u9e30\u9e31\u9e32\u9e33\u9e34\u9e35\u9e36\u9e37\u9e38\u9e39\u9e3a\u9e3b\u9e3c\u9e3d\u9e3e\u9e3f\u9e40\u9e41\u9e42\u9e43\u9e44\u9e45\u9e46\u9e47\u9e48\u9e49\u9e4a\u9e4b\u9e4c\u9e4d\u9e4e\u9e4f\u9e50\u9e51\u9e52\u9e53\u9e54\u9e55\u9e56\u9e57\u9e58\u9e59\u9e5a\u9e5b\u9e5c\u9e5d\u9e5e\u9e5f\u9e60\u9e61\u9e62\u9e63\u9e64\u9e65\u9e66\u9e67\u9e68\u9e69\u9e6a\u9e6b\u9e6c\u9e6d\u9e6e\u9e6f\u9e70\u9e71\u9e72\u9e73\u9e74\u9e75\u9e76\u9e77\u9e78\u9e79\u9e7a\u9e7b\u9e7c\u9e7d\u9e7e\u9e7f\u9e80\u9e81\u9e82\u9e83\u9e84\u9e85\u9e86\u9e87\u9e88\u9e89\u9e8a\u9e8b\u9e8c\u9e8d\u9e8e\u9e8f\u9e90\u9e91\u9e92\u9e93\u9e94\u9e95\u9e96\u9e97\u9e98\u9e99\u9e9a\u9e9b\u9e9c\u9e9d\u9e9e\u9e9f\u9ea0\u9ea1\u9ea2\u9ea3\u9ea4\u9ea5\u9ea6\u9ea7\u9ea8\u9ea9\u9eaa\u9eab\u9eac\u9ead\u9eae\u9eaf\u9eb0\u9eb1\u9eb2\u9eb3\u9eb4\u9eb5\u9eb6\u9eb7\u9eb8\u9eb9\u9eba\u9ebb\u9ebc\u9ebd\u9ebe\u9ebf\u9ec0\u9ec1\u9ec2\u9ec3\u9ec4\u9ec5\u9ec6\u9ec7\u9ec8\u9ec9\u9eca\u9ecb\u9ecc\u9ecd\u9ece\u9ecf\u9ed0\u9ed1\u9ed2\u9ed3\u9ed4\u9ed5\u9ed6\u9ed7\u9ed8\u9ed9\u9eda\u9edb\u9edc\u9edd\u9ede\u9edf\u9ee0\u9ee1\u9ee2\u9ee3\u9ee4\u9ee5\u9ee6\u9ee7\u9ee8\u9ee9\u9eea\u9eeb\u9eec\u9eed\u9eee\u9eef\u9ef0\u9ef1\u9ef2\u9ef3\u9ef4\u9ef5\u9ef6\u9ef7\u9ef8\u9ef9\u9efa\u9efb\u9efc\u9efd\u9efe\u9eff\u9f00\u9f01\u9f02\u9f03\u9f04\u9f05\u9f06\u9f07\u9f08\u9f09\u9f0a\u9f0b\u9f0c\u9f0d\u9f0e\u9f0f\u9f10\u9f11\u9f12\u9f13\u9f14\u9f15\u9f16\u9f17\u9f18\u9f19\u9f1a\u9f1b\u9f1c\u9f1d\u9f1e\u9f1f\u9f20\u9f21\u9f22\u9f23\u9f24\u9f25\u9f26\u9f27\u9f28\u9f29\u9f2a\u9f2b\u9f2c\u9f2d\u9f2e\u9f2f\u9f30\u9f31\u9f32\u9f33\u9f34\u9f35\u9f36\u9f37\u9f38\u9f39\u9f3a\u9f3b\u9f3c\u9f3d\u9f3e\u9f3f\u9f40\u9f41\u9f42\u9f43\u9f44\u9f45\u9f46\u9f47\u9f48\u9f49\u9f4a\u9f4b\u9f4c\u9f4d\u9f4e\u9f4f\u9f50\u9f51\u9f52\u9f53\u9f54\u9f55\u9f56\u9f57\u9f58\u9f59\u9f5a\u9f5b\u9f5c\u9f5d\u9f5e\u9f5f\u9f60\u9f61\u9f62\u9f63\u9f64\u9f65\u9f66\u9f67\u9f68\u9f69\u9f6a\u9f6b\u9f6c\u9f6d\u9f6e\u9f6f\u9f70\u9f71\u9f72\u9f73\u9f74\u9f75\u9f76\u9f77\u9f78\u9f79\u9f7a\u9f7b\u9f7c\u9f7d\u9f7e\u9f7f\u9f80\u9f81\u9f82\u9f83\u9f84\u9f85\u9f86\u9f87\u9f88\u9f89\u9f8a\u9f8b\u9f8c\u9f8d\u9f8e\u9f8f\u9f90\u9f91\u9f92\u9f93\u9f94\u9f95\u9f96\u9f97\u9f98\u9f99\u9f9a\u9f9b\u9f9c\u9f9d\u9f9e\u9f9f\u9fa0\u9fa1\u9fa2\u9fa3\u9fa4\u9fa5\u9fa6\u9fa7\u9fa8\u9fa9\u9faa\u9fab\u9fac\u9fad\u9fae\u9faf\u9fb0\u9fb1\u9fb2\u9fb3\u9fb4\u9fb5\u9fb6\u9fb7\u9fb8\u9fb9\u9fba\u9fbb\ua000\ua001\ua002\ua003\ua004\ua005\ua006\ua007\ua008\ua009\ua00a\ua00b\ua00c\ua00d\ua00e\ua00f\ua010\ua011\ua012\ua013\ua014\ua016\ua017\ua018\ua019\ua01a\ua01b\ua01c\ua01d\ua01e\ua01f\ua020\ua021\ua022\ua023\ua024\ua025\ua026\ua027\ua028\ua029\ua02a\ua02b\ua02c\ua02d\ua02e\ua02f\ua030\ua031\ua032\ua033\ua034\ua035\ua036\ua037\ua038\ua039\ua03a\ua03b\ua03c\ua03d\ua03e\ua03f\ua040\ua041\ua042\ua043\ua044\ua045\ua046\ua047\ua048\ua049\ua04a\ua04b\ua04c\ua04d\ua04e\ua04f\ua050\ua051\ua052\ua053\ua054\ua055\ua056\ua057\ua058\ua059\ua05a\ua05b\ua05c\ua05d\ua05e\ua05f\ua060\ua061\ua062\ua063\ua064\ua065\ua066\ua067\ua068\ua069\ua06a\ua06b\ua06c\ua06d\ua06e\ua06f\ua070\ua071\ua072\ua073\ua074\ua075\ua076\ua077\ua078\ua079\ua07a\ua07b\ua07c\ua07d\ua07e\ua07f\ua080\ua081\ua082\ua083\ua084\ua085\ua086\ua087\ua088\ua089\ua08a\ua08b\ua08c\ua08d\ua08e\ua08f\ua090\ua091\ua092\ua093\ua094\ua095\ua096\ua097\ua098\ua099\ua09a\ua09b\ua09c\ua09d\ua09e\ua09f\ua0a0\ua0a1\ua0a2\ua0a3\ua0a4\ua0a5\ua0a6\ua0a7\ua0a8\ua0a9\ua0aa\ua0ab\ua0ac\ua0ad\ua0ae\ua0af\ua0b0\ua0b1\ua0b2\ua0b3\ua0b4\ua0b5\ua0b6\ua0b7\ua0b8\ua0b9\ua0ba\ua0bb\ua0bc\ua0bd\ua0be\ua0bf\ua0c0\ua0c1\ua0c2\ua0c3\ua0c4\ua0c5\ua0c6\ua0c7\ua0c8\ua0c9\ua0ca\ua0cb\ua0cc\ua0cd\ua0ce\ua0cf\ua0d0\ua0d1\ua0d2\ua0d3\ua0d4\ua0d5\ua0d6\ua0d7\ua0d8\ua0d9\ua0da\ua0db\ua0dc\ua0dd\ua0de\ua0df\ua0e0\ua0e1\ua0e2\ua0e3\ua0e4\ua0e5\ua0e6\ua0e7\ua0e8\ua0e9\ua0ea\ua0eb\ua0ec\ua0ed\ua0ee\ua0ef\ua0f0\ua0f1\ua0f2\ua0f3\ua0f4\ua0f5\ua0f6\ua0f7\ua0f8\ua0f9\ua0fa\ua0fb\ua0fc\ua0fd\ua0fe\ua0ff\ua100\ua101\ua102\ua103\ua104\ua105\ua106\ua107\ua108\ua109\ua10a\ua10b\ua10c\ua10d\ua10e\ua10f\ua110\ua111\ua112\ua113\ua114\ua115\ua116\ua117\ua118\ua119\ua11a\ua11b\ua11c\ua11d\ua11e\ua11f\ua120\ua121\ua122\ua123\ua124\ua125\ua126\ua127\ua128\ua129\ua12a\ua12b\ua12c\ua12d\ua12e\ua12f\ua130\ua131\ua132\ua133\ua134\ua135\ua136\ua137\ua138\ua139\ua13a\ua13b\ua13c\ua13d\ua13e\ua13f\ua140\ua141\ua142\ua143\ua144\ua145\ua146\ua147\ua148\ua149\ua14a\ua14b\ua14c\ua14d\ua14e\ua14f\ua150\ua151\ua152\ua153\ua154\ua155\ua156\ua157\ua158\ua159\ua15a\ua15b\ua15c\ua15d\ua15e\ua15f\ua160\ua161\ua162\ua163\ua164\ua165\ua166\ua167\ua168\ua169\ua16a\ua16b\ua16c\ua16d\ua16e\ua16f\ua170\ua171\ua172\ua173\ua174\ua175\ua176\ua177\ua178\ua179\ua17a\ua17b\ua17c\ua17d\ua17e\ua17f\ua180\ua181\ua182\ua183\ua184\ua185\ua186\ua187\ua188\ua189\ua18a\ua18b\ua18c\ua18d\ua18e\ua18f\ua190\ua191\ua192\ua193\ua194\ua195\ua196\ua197\ua198\ua199\ua19a\ua19b\ua19c\ua19d\ua19e\ua19f\ua1a0\ua1a1\ua1a2\ua1a3\ua1a4\ua1a5\ua1a6\ua1a7\ua1a8\ua1a9\ua1aa\ua1ab\ua1ac\ua1ad\ua1ae\ua1af\ua1b0\ua1b1\ua1b2\ua1b3\ua1b4\ua1b5\ua1b6\ua1b7\ua1b8\ua1b9\ua1ba\ua1bb\ua1bc\ua1bd\ua1be\ua1bf\ua1c0\ua1c1\ua1c2\ua1c3\ua1c4\ua1c5\ua1c6\ua1c7\ua1c8\ua1c9\ua1ca\ua1cb\ua1cc\ua1cd\ua1ce\ua1cf\ua1d0\ua1d1\ua1d2\ua1d3\ua1d4\ua1d5\ua1d6\ua1d7\ua1d8\ua1d9\ua1da\ua1db\ua1dc\ua1dd\ua1de\ua1df\ua1e0\ua1e1\ua1e2\ua1e3\ua1e4\ua1e5\ua1e6\ua1e7\ua1e8\ua1e9\ua1ea\ua1eb\ua1ec\ua1ed\ua1ee\ua1ef\ua1f0\ua1f1\ua1f2\ua1f3\ua1f4\ua1f5\ua1f6\ua1f7\ua1f8\ua1f9\ua1fa\ua1fb\ua1fc\ua1fd\ua1fe\ua1ff\ua200\ua201\ua202\ua203\ua204\ua205\ua206\ua207\ua208\ua209\ua20a\ua20b\ua20c\ua20d\ua20e\ua20f\ua210\ua211\ua212\ua213\ua214\ua215\ua216\ua217\ua218\ua219\ua21a\ua21b\ua21c\ua21d\ua21e\ua21f\ua220\ua221\ua222\ua223\ua224\ua225\ua226\ua227\ua228\ua229\ua22a\ua22b\ua22c\ua22d\ua22e\ua22f\ua230\ua231\ua232\ua233\ua234\ua235\ua236\ua237\ua238\ua239\ua23a\ua23b\ua23c\ua23d\ua23e\ua23f\ua240\ua241\ua242\ua243\ua244\ua245\ua246\ua247\ua248\ua249\ua24a\ua24b\ua24c\ua24d\ua24e\ua24f\ua250\ua251\ua252\ua253\ua254\ua255\ua256\ua257\ua258\ua259\ua25a\ua25b\ua25c\ua25d\ua25e\ua25f\ua260\ua261\ua262\ua263\ua264\ua265\ua266\ua267\ua268\ua269\ua26a\ua26b\ua26c\ua26d\ua26e\ua26f\ua270\ua271\ua272\ua273\ua274\ua275\ua276\ua277\ua278\ua279\ua27a\ua27b\ua27c\ua27d\ua27e\ua27f\ua280\ua281\ua282\ua283\ua284\ua285\ua286\ua287\ua288\ua289\ua28a\ua28b\ua28c\ua28d\ua28e\ua28f\ua290\ua291\ua292\ua293\ua294\ua295\ua296\ua297\ua298\ua299\ua29a\ua29b\ua29c\ua29d\ua29e\ua29f\ua2a0\ua2a1\ua2a2\ua2a3\ua2a4\ua2a5\ua2a6\ua2a7\ua2a8\ua2a9\ua2aa\ua2ab\ua2ac\ua2ad\ua2ae\ua2af\ua2b0\ua2b1\ua2b2\ua2b3\ua2b4\ua2b5\ua2b6\ua2b7\ua2b8\ua2b9\ua2ba\ua2bb\ua2bc\ua2bd\ua2be\ua2bf\ua2c0\ua2c1\ua2c2\ua2c3\ua2c4\ua2c5\ua2c6\ua2c7\ua2c8\ua2c9\ua2ca\ua2cb\ua2cc\ua2cd\ua2ce\ua2cf\ua2d0\ua2d1\ua2d2\ua2d3\ua2d4\ua2d5\ua2d6\ua2d7\ua2d8\ua2d9\ua2da\ua2db\ua2dc\ua2dd\ua2de\ua2df\ua2e0\ua2e1\ua2e2\ua2e3\ua2e4\ua2e5\ua2e6\ua2e7\ua2e8\ua2e9\ua2ea\ua2eb\ua2ec\ua2ed\ua2ee\ua2ef\ua2f0\ua2f1\ua2f2\ua2f3\ua2f4\ua2f5\ua2f6\ua2f7\ua2f8\ua2f9\ua2fa\ua2fb\ua2fc\ua2fd\ua2fe\ua2ff\ua300\ua301\ua302\ua303\ua304\ua305\ua306\ua307\ua308\ua309\ua30a\ua30b\ua30c\ua30d\ua30e\ua30f\ua310\ua311\ua312\ua313\ua314\ua315\ua316\ua317\ua318\ua319\ua31a\ua31b\ua31c\ua31d\ua31e\ua31f\ua320\ua321\ua322\ua323\ua324\ua325\ua326\ua327\ua328\ua329\ua32a\ua32b\ua32c\ua32d\ua32e\ua32f\ua330\ua331\ua332\ua333\ua334\ua335\ua336\ua337\ua338\ua339\ua33a\ua33b\ua33c\ua33d\ua33e\ua33f\ua340\ua341\ua342\ua343\ua344\ua345\ua346\ua347\ua348\ua349\ua34a\ua34b\ua34c\ua34d\ua34e\ua34f\ua350\ua351\ua352\ua353\ua354\ua355\ua356\ua357\ua358\ua359\ua35a\ua35b\ua35c\ua35d\ua35e\ua35f\ua360\ua361\ua362\ua363\ua364\ua365\ua366\ua367\ua368\ua369\ua36a\ua36b\ua36c\ua36d\ua36e\ua36f\ua370\ua371\ua372\ua373\ua374\ua375\ua376\ua377\ua378\ua379\ua37a\ua37b\ua37c\ua37d\ua37e\ua37f\ua380\ua381\ua382\ua383\ua384\ua385\ua386\ua387\ua388\ua389\ua38a\ua38b\ua38c\ua38d\ua38e\ua38f\ua390\ua391\ua392\ua393\ua394\ua395\ua396\ua397\ua398\ua399\ua39a\ua39b\ua39c\ua39d\ua39e\ua39f\ua3a0\ua3a1\ua3a2\ua3a3\ua3a4\ua3a5\ua3a6\ua3a7\ua3a8\ua3a9\ua3aa\ua3ab\ua3ac\ua3ad\ua3ae\ua3af\ua3b0\ua3b1\ua3b2\ua3b3\ua3b4\ua3b5\ua3b6\ua3b7\ua3b8\ua3b9\ua3ba\ua3bb\ua3bc\ua3bd\ua3be\ua3bf\ua3c0\ua3c1\ua3c2\ua3c3\ua3c4\ua3c5\ua3c6\ua3c7\ua3c8\ua3c9\ua3ca\ua3cb\ua3cc\ua3cd\ua3ce\ua3cf\ua3d0\ua3d1\ua3d2\ua3d3\ua3d4\ua3d5\ua3d6\ua3d7\ua3d8\ua3d9\ua3da\ua3db\ua3dc\ua3dd\ua3de\ua3df\ua3e0\ua3e1\ua3e2\ua3e3\ua3e4\ua3e5\ua3e6\ua3e7\ua3e8\ua3e9\ua3ea\ua3eb\ua3ec\ua3ed\ua3ee\ua3ef\ua3f0\ua3f1\ua3f2\ua3f3\ua3f4\ua3f5\ua3f6\ua3f7\ua3f8\ua3f9\ua3fa\ua3fb\ua3fc\ua3fd\ua3fe\ua3ff\ua400\ua401\ua402\ua403\ua404\ua405\ua406\ua407\ua408\ua409\ua40a\ua40b\ua40c\ua40d\ua40e\ua40f\ua410\ua411\ua412\ua413\ua414\ua415\ua416\ua417\ua418\ua419\ua41a\ua41b\ua41c\ua41d\ua41e\ua41f\ua420\ua421\ua422\ua423\ua424\ua425\ua426\ua427\ua428\ua429\ua42a\ua42b\ua42c\ua42d\ua42e\ua42f\ua430\ua431\ua432\ua433\ua434\ua435\ua436\ua437\ua438\ua439\ua43a\ua43b\ua43c\ua43d\ua43e\ua43f\ua440\ua441\ua442\ua443\ua444\ua445\ua446\ua447\ua448\ua449\ua44a\ua44b\ua44c\ua44d\ua44e\ua44f\ua450\ua451\ua452\ua453\ua454\ua455\ua456\ua457\ua458\ua459\ua45a\ua45b\ua45c\ua45d\ua45e\ua45f\ua460\ua461\ua462\ua463\ua464\ua465\ua466\ua467\ua468\ua469\ua46a\ua46b\ua46c\ua46d\ua46e\ua46f\ua470\ua471\ua472\ua473\ua474\ua475\ua476\ua477\ua478\ua479\ua47a\ua47b\ua47c\ua47d\ua47e\ua47f\ua480\ua481\ua482\ua483\ua484\ua485\ua486\ua487\ua488\ua489\ua48a\ua48b\ua48c\ua800\ua801\ua803\ua804\ua805\ua807\ua808\ua809\ua80a\ua80c\ua80d\ua80e\ua80f\ua810\ua811\ua812\ua813\ua814\ua815\ua816\ua817\ua818\ua819\ua81a\ua81b\ua81c\ua81d\ua81e\ua81f\ua820\ua821\ua822\uac00\uac01\uac02\uac03\uac04\uac05\uac06\uac07\uac08\uac09\uac0a\uac0b\uac0c\uac0d\uac0e\uac0f\uac10\uac11\uac12\uac13\uac14\uac15\uac16\uac17\uac18\uac19\uac1a\uac1b\uac1c\uac1d\uac1e\uac1f\uac20\uac21\uac22\uac23\uac24\uac25\uac26\uac27\uac28\uac29\uac2a\uac2b\uac2c\uac2d\uac2e\uac2f\uac30\uac31\uac32\uac33\uac34\uac35\uac36\uac37\uac38\uac39\uac3a\uac3b\uac3c\uac3d\uac3e\uac3f\uac40\uac41\uac42\uac43\uac44\uac45\uac46\uac47\uac48\uac49\uac4a\uac4b\uac4c\uac4d\uac4e\uac4f\uac50\uac51\uac52\uac53\uac54\uac55\uac56\uac57\uac58\uac59\uac5a\uac5b\uac5c\uac5d\uac5e\uac5f\uac60\uac61\uac62\uac63\uac64\uac65\uac66\uac67\uac68\uac69\uac6a\uac6b\uac6c\uac6d\uac6e\uac6f\uac70\uac71\uac72\uac73\uac74\uac75\uac76\uac77\uac78\uac79\uac7a\uac7b\uac7c\uac7d\uac7e\uac7f\uac80\uac81\uac82\uac83\uac84\uac85\uac86\uac87\uac88\uac89\uac8a\uac8b\uac8c\uac8d\uac8e\uac8f\uac90\uac91\uac92\uac93\uac94\uac95\uac96\uac97\uac98\uac99\uac9a\uac9b\uac9c\uac9d\uac9e\uac9f\uaca0\uaca1\uaca2\uaca3\uaca4\uaca5\uaca6\uaca7\uaca8\uaca9\uacaa\uacab\uacac\uacad\uacae\uacaf\uacb0\uacb1\uacb2\uacb3\uacb4\uacb5\uacb6\uacb7\uacb8\uacb9\uacba\uacbb\uacbc\uacbd\uacbe\uacbf\uacc0\uacc1\uacc2\uacc3\uacc4\uacc5\uacc6\uacc7\uacc8\uacc9\uacca\uaccb\uaccc\uaccd\uacce\uaccf\uacd0\uacd1\uacd2\uacd3\uacd4\uacd5\uacd6\uacd7\uacd8\uacd9\uacda\uacdb\uacdc\uacdd\uacde\uacdf\uace0\uace1\uace2\uace3\uace4\uace5\uace6\uace7\uace8\uace9\uacea\uaceb\uacec\uaced\uacee\uacef\uacf0\uacf1\uacf2\uacf3\uacf4\uacf5\uacf6\uacf7\uacf8\uacf9\uacfa\uacfb\uacfc\uacfd\uacfe\uacff\uad00\uad01\uad02\uad03\uad04\uad05\uad06\uad07\uad08\uad09\uad0a\uad0b\uad0c\uad0d\uad0e\uad0f\uad10\uad11\uad12\uad13\uad14\uad15\uad16\uad17\uad18\uad19\uad1a\uad1b\uad1c\uad1d\uad1e\uad1f\uad20\uad21\uad22\uad23\uad24\uad25\uad26\uad27\uad28\uad29\uad2a\uad2b\uad2c\uad2d\uad2e\uad2f\uad30\uad31\uad32\uad33\uad34\uad35\uad36\uad37\uad38\uad39\uad3a\uad3b\uad3c\uad3d\uad3e\uad3f\uad40\uad41\uad42\uad43\uad44\uad45\uad46\uad47\uad48\uad49\uad4a\uad4b\uad4c\uad4d\uad4e\uad4f\uad50\uad51\uad52\uad53\uad54\uad55\uad56\uad57\uad58\uad59\uad5a\uad5b\uad5c\uad5d\uad5e\uad5f\uad60\uad61\uad62\uad63\uad64\uad65\uad66\uad67\uad68\uad69\uad6a\uad6b\uad6c\uad6d\uad6e\uad6f\uad70\uad71\uad72\uad73\uad74\uad75\uad76\uad77\uad78\uad79\uad7a\uad7b\uad7c\uad7d\uad7e\uad7f\uad80\uad81\uad82\uad83\uad84\uad85\uad86\uad87\uad88\uad89\uad8a\uad8b\uad8c\uad8d\uad8e\uad8f\uad90\uad91\uad92\uad93\uad94\uad95\uad96\uad97\uad98\uad99\uad9a\uad9b\uad9c\uad9d\uad9e\uad9f\uada0\uada1\uada2\uada3\uada4\uada5\uada6\uada7\uada8\uada9\uadaa\uadab\uadac\uadad\uadae\uadaf\uadb0\uadb1\uadb2\uadb3\uadb4\uadb5\uadb6\uadb7\uadb8\uadb9\uadba\uadbb\uadbc\uadbd\uadbe\uadbf\uadc0\uadc1\uadc2\uadc3\uadc4\uadc5\uadc6\uadc7\uadc8\uadc9\uadca\uadcb\uadcc\uadcd\uadce\uadcf\uadd0\uadd1\uadd2\uadd3\uadd4\uadd5\uadd6\uadd7\uadd8\uadd9\uadda\uaddb\uaddc\uaddd\uadde\uaddf\uade0\uade1\uade2\uade3\uade4\uade5\uade6\uade7\uade8\uade9\uadea\uadeb\uadec\uaded\uadee\uadef\uadf0\uadf1\uadf2\uadf3\uadf4\uadf5\uadf6\uadf7\uadf8\uadf9\uadfa\uadfb\uadfc\uadfd\uadfe\uadff\uae00\uae01\uae02\uae03\uae04\uae05\uae06\uae07\uae08\uae09\uae0a\uae0b\uae0c\uae0d\uae0e\uae0f\uae10\uae11\uae12\uae13\uae14\uae15\uae16\uae17\uae18\uae19\uae1a\uae1b\uae1c\uae1d\uae1e\uae1f\uae20\uae21\uae22\uae23\uae24\uae25\uae26\uae27\uae28\uae29\uae2a\uae2b\uae2c\uae2d\uae2e\uae2f\uae30\uae31\uae32\uae33\uae34\uae35\uae36\uae37\uae38\uae39\uae3a\uae3b\uae3c\uae3d\uae3e\uae3f\uae40\uae41\uae42\uae43\uae44\uae45\uae46\uae47\uae48\uae49\uae4a\uae4b\uae4c\uae4d\uae4e\uae4f\uae50\uae51\uae52\uae53\uae54\uae55\uae56\uae57\uae58\uae59\uae5a\uae5b\uae5c\uae5d\uae5e\uae5f\uae60\uae61\uae62\uae63\uae64\uae65\uae66\uae67\uae68\uae69\uae6a\uae6b\uae6c\uae6d\uae6e\uae6f\uae70\uae71\uae72\uae73\uae74\uae75\uae76\uae77\uae78\uae79\uae7a\uae7b\uae7c\uae7d\uae7e\uae7f\uae80\uae81\uae82\uae83\uae84\uae85\uae86\uae87\uae88\uae89\uae8a\uae8b\uae8c\uae8d\uae8e\uae8f\uae90\uae91\uae92\uae93\uae94\uae95\uae96\uae97\uae98\uae99\uae9a\uae9b\uae9c\uae9d\uae9e\uae9f\uaea0\uaea1\uaea2\uaea3\uaea4\uaea5\uaea6\uaea7\uaea8\uaea9\uaeaa\uaeab\uaeac\uaead\uaeae\uaeaf\uaeb0\uaeb1\uaeb2\uaeb3\uaeb4\uaeb5\uaeb6\uaeb7\uaeb8\uaeb9\uaeba\uaebb\uaebc\uaebd\uaebe\uaebf\uaec0\uaec1\uaec2\uaec3\uaec4\uaec5\uaec6\uaec7\uaec8\uaec9\uaeca\uaecb\uaecc\uaecd\uaece\uaecf\uaed0\uaed1\uaed2\uaed3\uaed4\uaed5\uaed6\uaed7\uaed8\uaed9\uaeda\uaedb\uaedc\uaedd\uaede\uaedf\uaee0\uaee1\uaee2\uaee3\uaee4\uaee5\uaee6\uaee7\uaee8\uaee9\uaeea\uaeeb\uaeec\uaeed\uaeee\uaeef\uaef0\uaef1\uaef2\uaef3\uaef4\uaef5\uaef6\uaef7\uaef8\uaef9\uaefa\uaefb\uaefc\uaefd\uaefe\uaeff\uaf00\uaf01\uaf02\uaf03\uaf04\uaf05\uaf06\uaf07\uaf08\uaf09\uaf0a\uaf0b\uaf0c\uaf0d\uaf0e\uaf0f\uaf10\uaf11\uaf12\uaf13\uaf14\uaf15\uaf16\uaf17\uaf18\uaf19\uaf1a\uaf1b\uaf1c\uaf1d\uaf1e\uaf1f\uaf20\uaf21\uaf22\uaf23\uaf24\uaf25\uaf26\uaf27\uaf28\uaf29\uaf2a\uaf2b\uaf2c\uaf2d\uaf2e\uaf2f\uaf30\uaf31\uaf32\uaf33\uaf34\uaf35\uaf36\uaf37\uaf38\uaf39\uaf3a\uaf3b\uaf3c\uaf3d\uaf3e\uaf3f\uaf40\uaf41\uaf42\uaf43\uaf44\uaf45\uaf46\uaf47\uaf48\uaf49\uaf4a\uaf4b\uaf4c\uaf4d\uaf4e\uaf4f\uaf50\uaf51\uaf52\uaf53\uaf54\uaf55\uaf56\uaf57\uaf58\uaf59\uaf5a\uaf5b\uaf5c\uaf5d\uaf5e\uaf5f\uaf60\uaf61\uaf62\uaf63\uaf64\uaf65\uaf66\uaf67\uaf68\uaf69\uaf6a\uaf6b\uaf6c\uaf6d\uaf6e\uaf6f\uaf70\uaf71\uaf72\uaf73\uaf74\uaf75\uaf76\uaf77\uaf78\uaf79\uaf7a\uaf7b\uaf7c\uaf7d\uaf7e\uaf7f\uaf80\uaf81\uaf82\uaf83\uaf84\uaf85\uaf86\uaf87\uaf88\uaf89\uaf8a\uaf8b\uaf8c\uaf8d\uaf8e\uaf8f\uaf90\uaf91\uaf92\uaf93\uaf94\uaf95\uaf96\uaf97\uaf98\uaf99\uaf9a\uaf9b\uaf9c\uaf9d\uaf9e\uaf9f\uafa0\uafa1\uafa2\uafa3\uafa4\uafa5\uafa6\uafa7\uafa8\uafa9\uafaa\uafab\uafac\uafad\uafae\uafaf\uafb0\uafb1\uafb2\uafb3\uafb4\uafb5\uafb6\uafb7\uafb8\uafb9\uafba\uafbb\uafbc\uafbd\uafbe\uafbf\uafc0\uafc1\uafc2\uafc3\uafc4\uafc5\uafc6\uafc7\uafc8\uafc9\uafca\uafcb\uafcc\uafcd\uafce\uafcf\uafd0\uafd1\uafd2\uafd3\uafd4\uafd5\uafd6\uafd7\uafd8\uafd9\uafda\uafdb\uafdc\uafdd\uafde\uafdf\uafe0\uafe1\uafe2\uafe3\uafe4\uafe5\uafe6\uafe7\uafe8\uafe9\uafea\uafeb\uafec\uafed\uafee\uafef\uaff0\uaff1\uaff2\uaff3\uaff4\uaff5\uaff6\uaff7\uaff8\uaff9\uaffa\uaffb\uaffc\uaffd\uaffe\uafff\ub000\ub001\ub002\ub003\ub004\ub005\ub006\ub007\ub008\ub009\ub00a\ub00b\ub00c\ub00d\ub00e\ub00f\ub010\ub011\ub012\ub013\ub014\ub015\ub016\ub017\ub018\ub019\ub01a\ub01b\ub01c\ub01d\ub01e\ub01f\ub020\ub021\ub022\ub023\ub024\ub025\ub026\ub027\ub028\ub029\ub02a\ub02b\ub02c\ub02d\ub02e\ub02f\ub030\ub031\ub032\ub033\ub034\ub035\ub036\ub037\ub038\ub039\ub03a\ub03b\ub03c\ub03d\ub03e\ub03f\ub040\ub041\ub042\ub043\ub044\ub045\ub046\ub047\ub048\ub049\ub04a\ub04b\ub04c\ub04d\ub04e\ub04f\ub050\ub051\ub052\ub053\ub054\ub055\ub056\ub057\ub058\ub059\ub05a\ub05b\ub05c\ub05d\ub05e\ub05f\ub060\ub061\ub062\ub063\ub064\ub065\ub066\ub067\ub068\ub069\ub06a\ub06b\ub06c\ub06d\ub06e\ub06f\ub070\ub071\ub072\ub073\ub074\ub075\ub076\ub077\ub078\ub079\ub07a\ub07b\ub07c\ub07d\ub07e\ub07f\ub080\ub081\ub082\ub083\ub084\ub085\ub086\ub087\ub088\ub089\ub08a\ub08b\ub08c\ub08d\ub08e\ub08f\ub090\ub091\ub092\ub093\ub094\ub095\ub096\ub097\ub098\ub099\ub09a\ub09b\ub09c\ub09d\ub09e\ub09f\ub0a0\ub0a1\ub0a2\ub0a3\ub0a4\ub0a5\ub0a6\ub0a7\ub0a8\ub0a9\ub0aa\ub0ab\ub0ac\ub0ad\ub0ae\ub0af\ub0b0\ub0b1\ub0b2\ub0b3\ub0b4\ub0b5\ub0b6\ub0b7\ub0b8\ub0b9\ub0ba\ub0bb\ub0bc\ub0bd\ub0be\ub0bf\ub0c0\ub0c1\ub0c2\ub0c3\ub0c4\ub0c5\ub0c6\ub0c7\ub0c8\ub0c9\ub0ca\ub0cb\ub0cc\ub0cd\ub0ce\ub0cf\ub0d0\ub0d1\ub0d2\ub0d3\ub0d4\ub0d5\ub0d6\ub0d7\ub0d8\ub0d9\ub0da\ub0db\ub0dc\ub0dd\ub0de\ub0df\ub0e0\ub0e1\ub0e2\ub0e3\ub0e4\ub0e5\ub0e6\ub0e7\ub0e8\ub0e9\ub0ea\ub0eb\ub0ec\ub0ed\ub0ee\ub0ef\ub0f0\ub0f1\ub0f2\ub0f3\ub0f4\ub0f5\ub0f6\ub0f7\ub0f8\ub0f9\ub0fa\ub0fb\ub0fc\ub0fd\ub0fe\ub0ff\ub100\ub101\ub102\ub103\ub104\ub105\ub106\ub107\ub108\ub109\ub10a\ub10b\ub10c\ub10d\ub10e\ub10f\ub110\ub111\ub112\ub113\ub114\ub115\ub116\ub117\ub118\ub119\ub11a\ub11b\ub11c\ub11d\ub11e\ub11f\ub120\ub121\ub122\ub123\ub124\ub125\ub126\ub127\ub128\ub129\ub12a\ub12b\ub12c\ub12d\ub12e\ub12f\ub130\ub131\ub132\ub133\ub134\ub135\ub136\ub137\ub138\ub139\ub13a\ub13b\ub13c\ub13d\ub13e\ub13f\ub140\ub141\ub142\ub143\ub144\ub145\ub146\ub147\ub148\ub149\ub14a\ub14b\ub14c\ub14d\ub14e\ub14f\ub150\ub151\ub152\ub153\ub154\ub155\ub156\ub157\ub158\ub159\ub15a\ub15b\ub15c\ub15d\ub15e\ub15f\ub160\ub161\ub162\ub163\ub164\ub165\ub166\ub167\ub168\ub169\ub16a\ub16b\ub16c\ub16d\ub16e\ub16f\ub170\ub171\ub172\ub173\ub174\ub175\ub176\ub177\ub178\ub179\ub17a\ub17b\ub17c\ub17d\ub17e\ub17f\ub180\ub181\ub182\ub183\ub184\ub185\ub186\ub187\ub188\ub189\ub18a\ub18b\ub18c\ub18d\ub18e\ub18f\ub190\ub191\ub192\ub193\ub194\ub195\ub196\ub197\ub198\ub199\ub19a\ub19b\ub19c\ub19d\ub19e\ub19f\ub1a0\ub1a1\ub1a2\ub1a3\ub1a4\ub1a5\ub1a6\ub1a7\ub1a8\ub1a9\ub1aa\ub1ab\ub1ac\ub1ad\ub1ae\ub1af\ub1b0\ub1b1\ub1b2\ub1b3\ub1b4\ub1b5\ub1b6\ub1b7\ub1b8\ub1b9\ub1ba\ub1bb\ub1bc\ub1bd\ub1be\ub1bf\ub1c0\ub1c1\ub1c2\ub1c3\ub1c4\ub1c5\ub1c6\ub1c7\ub1c8\ub1c9\ub1ca\ub1cb\ub1cc\ub1cd\ub1ce\ub1cf\ub1d0\ub1d1\ub1d2\ub1d3\ub1d4\ub1d5\ub1d6\ub1d7\ub1d8\ub1d9\ub1da\ub1db\ub1dc\ub1dd\ub1de\ub1df\ub1e0\ub1e1\ub1e2\ub1e3\ub1e4\ub1e5\ub1e6\ub1e7\ub1e8\ub1e9\ub1ea\ub1eb\ub1ec\ub1ed\ub1ee\ub1ef\ub1f0\ub1f1\ub1f2\ub1f3\ub1f4\ub1f5\ub1f6\ub1f7\ub1f8\ub1f9\ub1fa\ub1fb\ub1fc\ub1fd\ub1fe\ub1ff\ub200\ub201\ub202\ub203\ub204\ub205\ub206\ub207\ub208\ub209\ub20a\ub20b\ub20c\ub20d\ub20e\ub20f\ub210\ub211\ub212\ub213\ub214\ub215\ub216\ub217\ub218\ub219\ub21a\ub21b\ub21c\ub21d\ub21e\ub21f\ub220\ub221\ub222\ub223\ub224\ub225\ub226\ub227\ub228\ub229\ub22a\ub22b\ub22c\ub22d\ub22e\ub22f\ub230\ub231\ub232\ub233\ub234\ub235\ub236\ub237\ub238\ub239\ub23a\ub23b\ub23c\ub23d\ub23e\ub23f\ub240\ub241\ub242\ub243\ub244\ub245\ub246\ub247\ub248\ub249\ub24a\ub24b\ub24c\ub24d\ub24e\ub24f\ub250\ub251\ub252\ub253\ub254\ub255\ub256\ub257\ub258\ub259\ub25a\ub25b\ub25c\ub25d\ub25e\ub25f\ub260\ub261\ub262\ub263\ub264\ub265\ub266\ub267\ub268\ub269\ub26a\ub26b\ub26c\ub26d\ub26e\ub26f\ub270\ub271\ub272\ub273\ub274\ub275\ub276\ub277\ub278\ub279\ub27a\ub27b\ub27c\ub27d\ub27e\ub27f\ub280\ub281\ub282\ub283\ub284\ub285\ub286\ub287\ub288\ub289\ub28a\ub28b\ub28c\ub28d\ub28e\ub28f\ub290\ub291\ub292\ub293\ub294\ub295\ub296\ub297\ub298\ub299\ub29a\ub29b\ub29c\ub29d\ub29e\ub29f\ub2a0\ub2a1\ub2a2\ub2a3\ub2a4\ub2a5\ub2a6\ub2a7\ub2a8\ub2a9\ub2aa\ub2ab\ub2ac\ub2ad\ub2ae\ub2af\ub2b0\ub2b1\ub2b2\ub2b3\ub2b4\ub2b5\ub2b6\ub2b7\ub2b8\ub2b9\ub2ba\ub2bb\ub2bc\ub2bd\ub2be\ub2bf\ub2c0\ub2c1\ub2c2\ub2c3\ub2c4\ub2c5\ub2c6\ub2c7\ub2c8\ub2c9\ub2ca\ub2cb\ub2cc\ub2cd\ub2ce\ub2cf\ub2d0\ub2d1\ub2d2\ub2d3\ub2d4\ub2d5\ub2d6\ub2d7\ub2d8\ub2d9\ub2da\ub2db\ub2dc\ub2dd\ub2de\ub2df\ub2e0\ub2e1\ub2e2\ub2e3\ub2e4\ub2e5\ub2e6\ub2e7\ub2e8\ub2e9\ub2ea\ub2eb\ub2ec\ub2ed\ub2ee\ub2ef\ub2f0\ub2f1\ub2f2\ub2f3\ub2f4\ub2f5\ub2f6\ub2f7\ub2f8\ub2f9\ub2fa\ub2fb\ub2fc\ub2fd\ub2fe\ub2ff\ub300\ub301\ub302\ub303\ub304\ub305\ub306\ub307\ub308\ub309\ub30a\ub30b\ub30c\ub30d\ub30e\ub30f\ub310\ub311\ub312\ub313\ub314\ub315\ub316\ub317\ub318\ub319\ub31a\ub31b\ub31c\ub31d\ub31e\ub31f\ub320\ub321\ub322\ub323\ub324\ub325\ub326\ub327\ub328\ub329\ub32a\ub32b\ub32c\ub32d\ub32e\ub32f\ub330\ub331\ub332\ub333\ub334\ub335\ub336\ub337\ub338\ub339\ub33a\ub33b\ub33c\ub33d\ub33e\ub33f\ub340\ub341\ub342\ub343\ub344\ub345\ub346\ub347\ub348\ub349\ub34a\ub34b\ub34c\ub34d\ub34e\ub34f\ub350\ub351\ub352\ub353\ub354\ub355\ub356\ub357\ub358\ub359\ub35a\ub35b\ub35c\ub35d\ub35e\ub35f\ub360\ub361\ub362\ub363\ub364\ub365\ub366\ub367\ub368\ub369\ub36a\ub36b\ub36c\ub36d\ub36e\ub36f\ub370\ub371\ub372\ub373\ub374\ub375\ub376\ub377\ub378\ub379\ub37a\ub37b\ub37c\ub37d\ub37e\ub37f\ub380\ub381\ub382\ub383\ub384\ub385\ub386\ub387\ub388\ub389\ub38a\ub38b\ub38c\ub38d\ub38e\ub38f\ub390\ub391\ub392\ub393\ub394\ub395\ub396\ub397\ub398\ub399\ub39a\ub39b\ub39c\ub39d\ub39e\ub39f\ub3a0\ub3a1\ub3a2\ub3a3\ub3a4\ub3a5\ub3a6\ub3a7\ub3a8\ub3a9\ub3aa\ub3ab\ub3ac\ub3ad\ub3ae\ub3af\ub3b0\ub3b1\ub3b2\ub3b3\ub3b4\ub3b5\ub3b6\ub3b7\ub3b8\ub3b9\ub3ba\ub3bb\ub3bc\ub3bd\ub3be\ub3bf\ub3c0\ub3c1\ub3c2\ub3c3\ub3c4\ub3c5\ub3c6\ub3c7\ub3c8\ub3c9\ub3ca\ub3cb\ub3cc\ub3cd\ub3ce\ub3cf\ub3d0\ub3d1\ub3d2\ub3d3\ub3d4\ub3d5\ub3d6\ub3d7\ub3d8\ub3d9\ub3da\ub3db\ub3dc\ub3dd\ub3de\ub3df\ub3e0\ub3e1\ub3e2\ub3e3\ub3e4\ub3e5\ub3e6\ub3e7\ub3e8\ub3e9\ub3ea\ub3eb\ub3ec\ub3ed\ub3ee\ub3ef\ub3f0\ub3f1\ub3f2\ub3f3\ub3f4\ub3f5\ub3f6\ub3f7\ub3f8\ub3f9\ub3fa\ub3fb\ub3fc\ub3fd\ub3fe\ub3ff\ub400\ub401\ub402\ub403\ub404\ub405\ub406\ub407\ub408\ub409\ub40a\ub40b\ub40c\ub40d\ub40e\ub40f\ub410\ub411\ub412\ub413\ub414\ub415\ub416\ub417\ub418\ub419\ub41a\ub41b\ub41c\ub41d\ub41e\ub41f\ub420\ub421\ub422\ub423\ub424\ub425\ub426\ub427\ub428\ub429\ub42a\ub42b\ub42c\ub42d\ub42e\ub42f\ub430\ub431\ub432\ub433\ub434\ub435\ub436\ub437\ub438\ub439\ub43a\ub43b\ub43c\ub43d\ub43e\ub43f\ub440\ub441\ub442\ub443\ub444\ub445\ub446\ub447\ub448\ub449\ub44a\ub44b\ub44c\ub44d\ub44e\ub44f\ub450\ub451\ub452\ub453\ub454\ub455\ub456\ub457\ub458\ub459\ub45a\ub45b\ub45c\ub45d\ub45e\ub45f\ub460\ub461\ub462\ub463\ub464\ub465\ub466\ub467\ub468\ub469\ub46a\ub46b\ub46c\ub46d\ub46e\ub46f\ub470\ub471\ub472\ub473\ub474\ub475\ub476\ub477\ub478\ub479\ub47a\ub47b\ub47c\ub47d\ub47e\ub47f\ub480\ub481\ub482\ub483\ub484\ub485\ub486\ub487\ub488\ub489\ub48a\ub48b\ub48c\ub48d\ub48e\ub48f\ub490\ub491\ub492\ub493\ub494\ub495\ub496\ub497\ub498\ub499\ub49a\ub49b\ub49c\ub49d\ub49e\ub49f\ub4a0\ub4a1\ub4a2\ub4a3\ub4a4\ub4a5\ub4a6\ub4a7\ub4a8\ub4a9\ub4aa\ub4ab\ub4ac\ub4ad\ub4ae\ub4af\ub4b0\ub4b1\ub4b2\ub4b3\ub4b4\ub4b5\ub4b6\ub4b7\ub4b8\ub4b9\ub4ba\ub4bb\ub4bc\ub4bd\ub4be\ub4bf\ub4c0\ub4c1\ub4c2\ub4c3\ub4c4\ub4c5\ub4c6\ub4c7\ub4c8\ub4c9\ub4ca\ub4cb\ub4cc\ub4cd\ub4ce\ub4cf\ub4d0\ub4d1\ub4d2\ub4d3\ub4d4\ub4d5\ub4d6\ub4d7\ub4d8\ub4d9\ub4da\ub4db\ub4dc\ub4dd\ub4de\ub4df\ub4e0\ub4e1\ub4e2\ub4e3\ub4e4\ub4e5\ub4e6\ub4e7\ub4e8\ub4e9\ub4ea\ub4eb\ub4ec\ub4ed\ub4ee\ub4ef\ub4f0\ub4f1\ub4f2\ub4f3\ub4f4\ub4f5\ub4f6\ub4f7\ub4f8\ub4f9\ub4fa\ub4fb\ub4fc\ub4fd\ub4fe\ub4ff\ub500\ub501\ub502\ub503\ub504\ub505\ub506\ub507\ub508\ub509\ub50a\ub50b\ub50c\ub50d\ub50e\ub50f\ub510\ub511\ub512\ub513\ub514\ub515\ub516\ub517\ub518\ub519\ub51a\ub51b\ub51c\ub51d\ub51e\ub51f\ub520\ub521\ub522\ub523\ub524\ub525\ub526\ub527\ub528\ub529\ub52a\ub52b\ub52c\ub52d\ub52e\ub52f\ub530\ub531\ub532\ub533\ub534\ub535\ub536\ub537\ub538\ub539\ub53a\ub53b\ub53c\ub53d\ub53e\ub53f\ub540\ub541\ub542\ub543\ub544\ub545\ub546\ub547\ub548\ub549\ub54a\ub54b\ub54c\ub54d\ub54e\ub54f\ub550\ub551\ub552\ub553\ub554\ub555\ub556\ub557\ub558\ub559\ub55a\ub55b\ub55c\ub55d\ub55e\ub55f\ub560\ub561\ub562\ub563\ub564\ub565\ub566\ub567\ub568\ub569\ub56a\ub56b\ub56c\ub56d\ub56e\ub56f\ub570\ub571\ub572\ub573\ub574\ub575\ub576\ub577\ub578\ub579\ub57a\ub57b\ub57c\ub57d\ub57e\ub57f\ub580\ub581\ub582\ub583\ub584\ub585\ub586\ub587\ub588\ub589\ub58a\ub58b\ub58c\ub58d\ub58e\ub58f\ub590\ub591\ub592\ub593\ub594\ub595\ub596\ub597\ub598\ub599\ub59a\ub59b\ub59c\ub59d\ub59e\ub59f\ub5a0\ub5a1\ub5a2\ub5a3\ub5a4\ub5a5\ub5a6\ub5a7\ub5a8\ub5a9\ub5aa\ub5ab\ub5ac\ub5ad\ub5ae\ub5af\ub5b0\ub5b1\ub5b2\ub5b3\ub5b4\ub5b5\ub5b6\ub5b7\ub5b8\ub5b9\ub5ba\ub5bb\ub5bc\ub5bd\ub5be\ub5bf\ub5c0\ub5c1\ub5c2\ub5c3\ub5c4\ub5c5\ub5c6\ub5c7\ub5c8\ub5c9\ub5ca\ub5cb\ub5cc\ub5cd\ub5ce\ub5cf\ub5d0\ub5d1\ub5d2\ub5d3\ub5d4\ub5d5\ub5d6\ub5d7\ub5d8\ub5d9\ub5da\ub5db\ub5dc\ub5dd\ub5de\ub5df\ub5e0\ub5e1\ub5e2\ub5e3\ub5e4\ub5e5\ub5e6\ub5e7\ub5e8\ub5e9\ub5ea\ub5eb\ub5ec\ub5ed\ub5ee\ub5ef\ub5f0\ub5f1\ub5f2\ub5f3\ub5f4\ub5f5\ub5f6\ub5f7\ub5f8\ub5f9\ub5fa\ub5fb\ub5fc\ub5fd\ub5fe\ub5ff\ub600\ub601\ub602\ub603\ub604\ub605\ub606\ub607\ub608\ub609\ub60a\ub60b\ub60c\ub60d\ub60e\ub60f\ub610\ub611\ub612\ub613\ub614\ub615\ub616\ub617\ub618\ub619\ub61a\ub61b\ub61c\ub61d\ub61e\ub61f\ub620\ub621\ub622\ub623\ub624\ub625\ub626\ub627\ub628\ub629\ub62a\ub62b\ub62c\ub62d\ub62e\ub62f\ub630\ub631\ub632\ub633\ub634\ub635\ub636\ub637\ub638\ub639\ub63a\ub63b\ub63c\ub63d\ub63e\ub63f\ub640\ub641\ub642\ub643\ub644\ub645\ub646\ub647\ub648\ub649\ub64a\ub64b\ub64c\ub64d\ub64e\ub64f\ub650\ub651\ub652\ub653\ub654\ub655\ub656\ub657\ub658\ub659\ub65a\ub65b\ub65c\ub65d\ub65e\ub65f\ub660\ub661\ub662\ub663\ub664\ub665\ub666\ub667\ub668\ub669\ub66a\ub66b\ub66c\ub66d\ub66e\ub66f\ub670\ub671\ub672\ub673\ub674\ub675\ub676\ub677\ub678\ub679\ub67a\ub67b\ub67c\ub67d\ub67e\ub67f\ub680\ub681\ub682\ub683\ub684\ub685\ub686\ub687\ub688\ub689\ub68a\ub68b\ub68c\ub68d\ub68e\ub68f\ub690\ub691\ub692\ub693\ub694\ub695\ub696\ub697\ub698\ub699\ub69a\ub69b\ub69c\ub69d\ub69e\ub69f\ub6a0\ub6a1\ub6a2\ub6a3\ub6a4\ub6a5\ub6a6\ub6a7\ub6a8\ub6a9\ub6aa\ub6ab\ub6ac\ub6ad\ub6ae\ub6af\ub6b0\ub6b1\ub6b2\ub6b3\ub6b4\ub6b5\ub6b6\ub6b7\ub6b8\ub6b9\ub6ba\ub6bb\ub6bc\ub6bd\ub6be\ub6bf\ub6c0\ub6c1\ub6c2\ub6c3\ub6c4\ub6c5\ub6c6\ub6c7\ub6c8\ub6c9\ub6ca\ub6cb\ub6cc\ub6cd\ub6ce\ub6cf\ub6d0\ub6d1\ub6d2\ub6d3\ub6d4\ub6d5\ub6d6\ub6d7\ub6d8\ub6d9\ub6da\ub6db\ub6dc\ub6dd\ub6de\ub6df\ub6e0\ub6e1\ub6e2\ub6e3\ub6e4\ub6e5\ub6e6\ub6e7\ub6e8\ub6e9\ub6ea\ub6eb\ub6ec\ub6ed\ub6ee\ub6ef\ub6f0\ub6f1\ub6f2\ub6f3\ub6f4\ub6f5\ub6f6\ub6f7\ub6f8\ub6f9\ub6fa\ub6fb\ub6fc\ub6fd\ub6fe\ub6ff\ub700\ub701\ub702\ub703\ub704\ub705\ub706\ub707\ub708\ub709\ub70a\ub70b\ub70c\ub70d\ub70e\ub70f\ub710\ub711\ub712\ub713\ub714\ub715\ub716\ub717\ub718\ub719\ub71a\ub71b\ub71c\ub71d\ub71e\ub71f\ub720\ub721\ub722\ub723\ub724\ub725\ub726\ub727\ub728\ub729\ub72a\ub72b\ub72c\ub72d\ub72e\ub72f\ub730\ub731\ub732\ub733\ub734\ub735\ub736\ub737\ub738\ub739\ub73a\ub73b\ub73c\ub73d\ub73e\ub73f\ub740\ub741\ub742\ub743\ub744\ub745\ub746\ub747\ub748\ub749\ub74a\ub74b\ub74c\ub74d\ub74e\ub74f\ub750\ub751\ub752\ub753\ub754\ub755\ub756\ub757\ub758\ub759\ub75a\ub75b\ub75c\ub75d\ub75e\ub75f\ub760\ub761\ub762\ub763\ub764\ub765\ub766\ub767\ub768\ub769\ub76a\ub76b\ub76c\ub76d\ub76e\ub76f\ub770\ub771\ub772\ub773\ub774\ub775\ub776\ub777\ub778\ub779\ub77a\ub77b\ub77c\ub77d\ub77e\ub77f\ub780\ub781\ub782\ub783\ub784\ub785\ub786\ub787\ub788\ub789\ub78a\ub78b\ub78c\ub78d\ub78e\ub78f\ub790\ub791\ub792\ub793\ub794\ub795\ub796\ub797\ub798\ub799\ub79a\ub79b\ub79c\ub79d\ub79e\ub79f\ub7a0\ub7a1\ub7a2\ub7a3\ub7a4\ub7a5\ub7a6\ub7a7\ub7a8\ub7a9\ub7aa\ub7ab\ub7ac\ub7ad\ub7ae\ub7af\ub7b0\ub7b1\ub7b2\ub7b3\ub7b4\ub7b5\ub7b6\ub7b7\ub7b8\ub7b9\ub7ba\ub7bb\ub7bc\ub7bd\ub7be\ub7bf\ub7c0\ub7c1\ub7c2\ub7c3\ub7c4\ub7c5\ub7c6\ub7c7\ub7c8\ub7c9\ub7ca\ub7cb\ub7cc\ub7cd\ub7ce\ub7cf\ub7d0\ub7d1\ub7d2\ub7d3\ub7d4\ub7d5\ub7d6\ub7d7\ub7d8\ub7d9\ub7da\ub7db\ub7dc\ub7dd\ub7de\ub7df\ub7e0\ub7e1\ub7e2\ub7e3\ub7e4\ub7e5\ub7e6\ub7e7\ub7e8\ub7e9\ub7ea\ub7eb\ub7ec\ub7ed\ub7ee\ub7ef\ub7f0\ub7f1\ub7f2\ub7f3\ub7f4\ub7f5\ub7f6\ub7f7\ub7f8\ub7f9\ub7fa\ub7fb\ub7fc\ub7fd\ub7fe\ub7ff\ub800\ub801\ub802\ub803\ub804\ub805\ub806\ub807\ub808\ub809\ub80a\ub80b\ub80c\ub80d\ub80e\ub80f\ub810\ub811\ub812\ub813\ub814\ub815\ub816\ub817\ub818\ub819\ub81a\ub81b\ub81c\ub81d\ub81e\ub81f\ub820\ub821\ub822\ub823\ub824\ub825\ub826\ub827\ub828\ub829\ub82a\ub82b\ub82c\ub82d\ub82e\ub82f\ub830\ub831\ub832\ub833\ub834\ub835\ub836\ub837\ub838\ub839\ub83a\ub83b\ub83c\ub83d\ub83e\ub83f\ub840\ub841\ub842\ub843\ub844\ub845\ub846\ub847\ub848\ub849\ub84a\ub84b\ub84c\ub84d\ub84e\ub84f\ub850\ub851\ub852\ub853\ub854\ub855\ub856\ub857\ub858\ub859\ub85a\ub85b\ub85c\ub85d\ub85e\ub85f\ub860\ub861\ub862\ub863\ub864\ub865\ub866\ub867\ub868\ub869\ub86a\ub86b\ub86c\ub86d\ub86e\ub86f\ub870\ub871\ub872\ub873\ub874\ub875\ub876\ub877\ub878\ub879\ub87a\ub87b\ub87c\ub87d\ub87e\ub87f\ub880\ub881\ub882\ub883\ub884\ub885\ub886\ub887\ub888\ub889\ub88a\ub88b\ub88c\ub88d\ub88e\ub88f\ub890\ub891\ub892\ub893\ub894\ub895\ub896\ub897\ub898\ub899\ub89a\ub89b\ub89c\ub89d\ub89e\ub89f\ub8a0\ub8a1\ub8a2\ub8a3\ub8a4\ub8a5\ub8a6\ub8a7\ub8a8\ub8a9\ub8aa\ub8ab\ub8ac\ub8ad\ub8ae\ub8af\ub8b0\ub8b1\ub8b2\ub8b3\ub8b4\ub8b5\ub8b6\ub8b7\ub8b8\ub8b9\ub8ba\ub8bb\ub8bc\ub8bd\ub8be\ub8bf\ub8c0\ub8c1\ub8c2\ub8c3\ub8c4\ub8c5\ub8c6\ub8c7\ub8c8\ub8c9\ub8ca\ub8cb\ub8cc\ub8cd\ub8ce\ub8cf\ub8d0\ub8d1\ub8d2\ub8d3\ub8d4\ub8d5\ub8d6\ub8d7\ub8d8\ub8d9\ub8da\ub8db\ub8dc\ub8dd\ub8de\ub8df\ub8e0\ub8e1\ub8e2\ub8e3\ub8e4\ub8e5\ub8e6\ub8e7\ub8e8\ub8e9\ub8ea\ub8eb\ub8ec\ub8ed\ub8ee\ub8ef\ub8f0\ub8f1\ub8f2\ub8f3\ub8f4\ub8f5\ub8f6\ub8f7\ub8f8\ub8f9\ub8fa\ub8fb\ub8fc\ub8fd\ub8fe\ub8ff\ub900\ub901\ub902\ub903\ub904\ub905\ub906\ub907\ub908\ub909\ub90a\ub90b\ub90c\ub90d\ub90e\ub90f\ub910\ub911\ub912\ub913\ub914\ub915\ub916\ub917\ub918\ub919\ub91a\ub91b\ub91c\ub91d\ub91e\ub91f\ub920\ub921\ub922\ub923\ub924\ub925\ub926\ub927\ub928\ub929\ub92a\ub92b\ub92c\ub92d\ub92e\ub92f\ub930\ub931\ub932\ub933\ub934\ub935\ub936\ub937\ub938\ub939\ub93a\ub93b\ub93c\ub93d\ub93e\ub93f\ub940\ub941\ub942\ub943\ub944\ub945\ub946\ub947\ub948\ub949\ub94a\ub94b\ub94c\ub94d\ub94e\ub94f\ub950\ub951\ub952\ub953\ub954\ub955\ub956\ub957\ub958\ub959\ub95a\ub95b\ub95c\ub95d\ub95e\ub95f\ub960\ub961\ub962\ub963\ub964\ub965\ub966\ub967\ub968\ub969\ub96a\ub96b\ub96c\ub96d\ub96e\ub96f\ub970\ub971\ub972\ub973\ub974\ub975\ub976\ub977\ub978\ub979\ub97a\ub97b\ub97c\ub97d\ub97e\ub97f\ub980\ub981\ub982\ub983\ub984\ub985\ub986\ub987\ub988\ub989\ub98a\ub98b\ub98c\ub98d\ub98e\ub98f\ub990\ub991\ub992\ub993\ub994\ub995\ub996\ub997\ub998\ub999\ub99a\ub99b\ub99c\ub99d\ub99e\ub99f\ub9a0\ub9a1\ub9a2\ub9a3\ub9a4\ub9a5\ub9a6\ub9a7\ub9a8\ub9a9\ub9aa\ub9ab\ub9ac\ub9ad\ub9ae\ub9af\ub9b0\ub9b1\ub9b2\ub9b3\ub9b4\ub9b5\ub9b6\ub9b7\ub9b8\ub9b9\ub9ba\ub9bb\ub9bc\ub9bd\ub9be\ub9bf\ub9c0\ub9c1\ub9c2\ub9c3\ub9c4\ub9c5\ub9c6\ub9c7\ub9c8\ub9c9\ub9ca\ub9cb\ub9cc\ub9cd\ub9ce\ub9cf\ub9d0\ub9d1\ub9d2\ub9d3\ub9d4\ub9d5\ub9d6\ub9d7\ub9d8\ub9d9\ub9da\ub9db\ub9dc\ub9dd\ub9de\ub9df\ub9e0\ub9e1\ub9e2\ub9e3\ub9e4\ub9e5\ub9e6\ub9e7\ub9e8\ub9e9\ub9ea\ub9eb\ub9ec\ub9ed\ub9ee\ub9ef\ub9f0\ub9f1\ub9f2\ub9f3\ub9f4\ub9f5\ub9f6\ub9f7\ub9f8\ub9f9\ub9fa\ub9fb\ub9fc\ub9fd\ub9fe\ub9ff\uba00\uba01\uba02\uba03\uba04\uba05\uba06\uba07\uba08\uba09\uba0a\uba0b\uba0c\uba0d\uba0e\uba0f\uba10\uba11\uba12\uba13\uba14\uba15\uba16\uba17\uba18\uba19\uba1a\uba1b\uba1c\uba1d\uba1e\uba1f\uba20\uba21\uba22\uba23\uba24\uba25\uba26\uba27\uba28\uba29\uba2a\uba2b\uba2c\uba2d\uba2e\uba2f\uba30\uba31\uba32\uba33\uba34\uba35\uba36\uba37\uba38\uba39\uba3a\uba3b\uba3c\uba3d\uba3e\uba3f\uba40\uba41\uba42\uba43\uba44\uba45\uba46\uba47\uba48\uba49\uba4a\uba4b\uba4c\uba4d\uba4e\uba4f\uba50\uba51\uba52\uba53\uba54\uba55\uba56\uba57\uba58\uba59\uba5a\uba5b\uba5c\uba5d\uba5e\uba5f\uba60\uba61\uba62\uba63\uba64\uba65\uba66\uba67\uba68\uba69\uba6a\uba6b\uba6c\uba6d\uba6e\uba6f\uba70\uba71\uba72\uba73\uba74\uba75\uba76\uba77\uba78\uba79\uba7a\uba7b\uba7c\uba7d\uba7e\uba7f\uba80\uba81\uba82\uba83\uba84\uba85\uba86\uba87\uba88\uba89\uba8a\uba8b\uba8c\uba8d\uba8e\uba8f\uba90\uba91\uba92\uba93\uba94\uba95\uba96\uba97\uba98\uba99\uba9a\uba9b\uba9c\uba9d\uba9e\uba9f\ubaa0\ubaa1\ubaa2\ubaa3\ubaa4\ubaa5\ubaa6\ubaa7\ubaa8\ubaa9\ubaaa\ubaab\ubaac\ubaad\ubaae\ubaaf\ubab0\ubab1\ubab2\ubab3\ubab4\ubab5\ubab6\ubab7\ubab8\ubab9\ubaba\ubabb\ubabc\ubabd\ubabe\ubabf\ubac0\ubac1\ubac2\ubac3\ubac4\ubac5\ubac6\ubac7\ubac8\ubac9\ubaca\ubacb\ubacc\ubacd\ubace\ubacf\ubad0\ubad1\ubad2\ubad3\ubad4\ubad5\ubad6\ubad7\ubad8\ubad9\ubada\ubadb\ubadc\ubadd\ubade\ubadf\ubae0\ubae1\ubae2\ubae3\ubae4\ubae5\ubae6\ubae7\ubae8\ubae9\ubaea\ubaeb\ubaec\ubaed\ubaee\ubaef\ubaf0\ubaf1\ubaf2\ubaf3\ubaf4\ubaf5\ubaf6\ubaf7\ubaf8\ubaf9\ubafa\ubafb\ubafc\ubafd\ubafe\ubaff\ubb00\ubb01\ubb02\ubb03\ubb04\ubb05\ubb06\ubb07\ubb08\ubb09\ubb0a\ubb0b\ubb0c\ubb0d\ubb0e\ubb0f\ubb10\ubb11\ubb12\ubb13\ubb14\ubb15\ubb16\ubb17\ubb18\ubb19\ubb1a\ubb1b\ubb1c\ubb1d\ubb1e\ubb1f\ubb20\ubb21\ubb22\ubb23\ubb24\ubb25\ubb26\ubb27\ubb28\ubb29\ubb2a\ubb2b\ubb2c\ubb2d\ubb2e\ubb2f\ubb30\ubb31\ubb32\ubb33\ubb34\ubb35\ubb36\ubb37\ubb38\ubb39\ubb3a\ubb3b\ubb3c\ubb3d\ubb3e\ubb3f\ubb40\ubb41\ubb42\ubb43\ubb44\ubb45\ubb46\ubb47\ubb48\ubb49\ubb4a\ubb4b\ubb4c\ubb4d\ubb4e\ubb4f\ubb50\ubb51\ubb52\ubb53\ubb54\ubb55\ubb56\ubb57\ubb58\ubb59\ubb5a\ubb5b\ubb5c\ubb5d\ubb5e\ubb5f\ubb60\ubb61\ubb62\ubb63\ubb64\ubb65\ubb66\ubb67\ubb68\ubb69\ubb6a\ubb6b\ubb6c\ubb6d\ubb6e\ubb6f\ubb70\ubb71\ubb72\ubb73\ubb74\ubb75\ubb76\ubb77\ubb78\ubb79\ubb7a\ubb7b\ubb7c\ubb7d\ubb7e\ubb7f\ubb80\ubb81\ubb82\ubb83\ubb84\ubb85\ubb86\ubb87\ubb88\ubb89\ubb8a\ubb8b\ubb8c\ubb8d\ubb8e\ubb8f\ubb90\ubb91\ubb92\ubb93\ubb94\ubb95\ubb96\ubb97\ubb98\ubb99\ubb9a\ubb9b\ubb9c\ubb9d\ubb9e\ubb9f\ubba0\ubba1\ubba2\ubba3\ubba4\ubba5\ubba6\ubba7\ubba8\ubba9\ubbaa\ubbab\ubbac\ubbad\ubbae\ubbaf\ubbb0\ubbb1\ubbb2\ubbb3\ubbb4\ubbb5\ubbb6\ubbb7\ubbb8\ubbb9\ubbba\ubbbb\ubbbc\ubbbd\ubbbe\ubbbf\ubbc0\ubbc1\ubbc2\ubbc3\ubbc4\ubbc5\ubbc6\ubbc7\ubbc8\ubbc9\ubbca\ubbcb\ubbcc\ubbcd\ubbce\ubbcf\ubbd0\ubbd1\ubbd2\ubbd3\ubbd4\ubbd5\ubbd6\ubbd7\ubbd8\ubbd9\ubbda\ubbdb\ubbdc\ubbdd\ubbde\ubbdf\ubbe0\ubbe1\ubbe2\ubbe3\ubbe4\ubbe5\ubbe6\ubbe7\ubbe8\ubbe9\ubbea\ubbeb\ubbec\ubbed\ubbee\ubbef\ubbf0\ubbf1\ubbf2\ubbf3\ubbf4\ubbf5\ubbf6\ubbf7\ubbf8\ubbf9\ubbfa\ubbfb\ubbfc\ubbfd\ubbfe\ubbff\ubc00\ubc01\ubc02\ubc03\ubc04\ubc05\ubc06\ubc07\ubc08\ubc09\ubc0a\ubc0b\ubc0c\ubc0d\ubc0e\ubc0f\ubc10\ubc11\ubc12\ubc13\ubc14\ubc15\ubc16\ubc17\ubc18\ubc19\ubc1a\ubc1b\ubc1c\ubc1d\ubc1e\ubc1f\ubc20\ubc21\ubc22\ubc23\ubc24\ubc25\ubc26\ubc27\ubc28\ubc29\ubc2a\ubc2b\ubc2c\ubc2d\ubc2e\ubc2f\ubc30\ubc31\ubc32\ubc33\ubc34\ubc35\ubc36\ubc37\ubc38\ubc39\ubc3a\ubc3b\ubc3c\ubc3d\ubc3e\ubc3f\ubc40\ubc41\ubc42\ubc43\ubc44\ubc45\ubc46\ubc47\ubc48\ubc49\ubc4a\ubc4b\ubc4c\ubc4d\ubc4e\ubc4f\ubc50\ubc51\ubc52\ubc53\ubc54\ubc55\ubc56\ubc57\ubc58\ubc59\ubc5a\ubc5b\ubc5c\ubc5d\ubc5e\ubc5f\ubc60\ubc61\ubc62\ubc63\ubc64\ubc65\ubc66\ubc67\ubc68\ubc69\ubc6a\ubc6b\ubc6c\ubc6d\ubc6e\ubc6f\ubc70\ubc71\ubc72\ubc73\ubc74\ubc75\ubc76\ubc77\ubc78\ubc79\ubc7a\ubc7b\ubc7c\ubc7d\ubc7e\ubc7f\ubc80\ubc81\ubc82\ubc83\ubc84\ubc85\ubc86\ubc87\ubc88\ubc89\ubc8a\ubc8b\ubc8c\ubc8d\ubc8e\ubc8f\ubc90\ubc91\ubc92\ubc93\ubc94\ubc95\ubc96\ubc97\ubc98\ubc99\ubc9a\ubc9b\ubc9c\ubc9d\ubc9e\ubc9f\ubca0\ubca1\ubca2\ubca3\ubca4\ubca5\ubca6\ubca7\ubca8\ubca9\ubcaa\ubcab\ubcac\ubcad\ubcae\ubcaf\ubcb0\ubcb1\ubcb2\ubcb3\ubcb4\ubcb5\ubcb6\ubcb7\ubcb8\ubcb9\ubcba\ubcbb\ubcbc\ubcbd\ubcbe\ubcbf\ubcc0\ubcc1\ubcc2\ubcc3\ubcc4\ubcc5\ubcc6\ubcc7\ubcc8\ubcc9\ubcca\ubccb\ubccc\ubccd\ubcce\ubccf\ubcd0\ubcd1\ubcd2\ubcd3\ubcd4\ubcd5\ubcd6\ubcd7\ubcd8\ubcd9\ubcda\ubcdb\ubcdc\ubcdd\ubcde\ubcdf\ubce0\ubce1\ubce2\ubce3\ubce4\ubce5\ubce6\ubce7\ubce8\ubce9\ubcea\ubceb\ubcec\ubced\ubcee\ubcef\ubcf0\ubcf1\ubcf2\ubcf3\ubcf4\ubcf5\ubcf6\ubcf7\ubcf8\ubcf9\ubcfa\ubcfb\ubcfc\ubcfd\ubcfe\ubcff\ubd00\ubd01\ubd02\ubd03\ubd04\ubd05\ubd06\ubd07\ubd08\ubd09\ubd0a\ubd0b\ubd0c\ubd0d\ubd0e\ubd0f\ubd10\ubd11\ubd12\ubd13\ubd14\ubd15\ubd16\ubd17\ubd18\ubd19\ubd1a\ubd1b\ubd1c\ubd1d\ubd1e\ubd1f\ubd20\ubd21\ubd22\ubd23\ubd24\ubd25\ubd26\ubd27\ubd28\ubd29\ubd2a\ubd2b\ubd2c\ubd2d\ubd2e\ubd2f\ubd30\ubd31\ubd32\ubd33\ubd34\ubd35\ubd36\ubd37\ubd38\ubd39\ubd3a\ubd3b\ubd3c\ubd3d\ubd3e\ubd3f\ubd40\ubd41\ubd42\ubd43\ubd44\ubd45\ubd46\ubd47\ubd48\ubd49\ubd4a\ubd4b\ubd4c\ubd4d\ubd4e\ubd4f\ubd50\ubd51\ubd52\ubd53\ubd54\ubd55\ubd56\ubd57\ubd58\ubd59\ubd5a\ubd5b\ubd5c\ubd5d\ubd5e\ubd5f\ubd60\ubd61\ubd62\ubd63\ubd64\ubd65\ubd66\ubd67\ubd68\ubd69\ubd6a\ubd6b\ubd6c\ubd6d\ubd6e\ubd6f\ubd70\ubd71\ubd72\ubd73\ubd74\ubd75\ubd76\ubd77\ubd78\ubd79\ubd7a\ubd7b\ubd7c\ubd7d\ubd7e\ubd7f\ubd80\ubd81\ubd82\ubd83\ubd84\ubd85\ubd86\ubd87\ubd88\ubd89\ubd8a\ubd8b\ubd8c\ubd8d\ubd8e\ubd8f\ubd90\ubd91\ubd92\ubd93\ubd94\ubd95\ubd96\ubd97\ubd98\ubd99\ubd9a\ubd9b\ubd9c\ubd9d\ubd9e\ubd9f\ubda0\ubda1\ubda2\ubda3\ubda4\ubda5\ubda6\ubda7\ubda8\ubda9\ubdaa\ubdab\ubdac\ubdad\ubdae\ubdaf\ubdb0\ubdb1\ubdb2\ubdb3\ubdb4\ubdb5\ubdb6\ubdb7\ubdb8\ubdb9\ubdba\ubdbb\ubdbc\ubdbd\ubdbe\ubdbf\ubdc0\ubdc1\ubdc2\ubdc3\ubdc4\ubdc5\ubdc6\ubdc7\ubdc8\ubdc9\ubdca\ubdcb\ubdcc\ubdcd\ubdce\ubdcf\ubdd0\ubdd1\ubdd2\ubdd3\ubdd4\ubdd5\ubdd6\ubdd7\ubdd8\ubdd9\ubdda\ubddb\ubddc\ubddd\ubdde\ubddf\ubde0\ubde1\ubde2\ubde3\ubde4\ubde5\ubde6\ubde7\ubde8\ubde9\ubdea\ubdeb\ubdec\ubded\ubdee\ubdef\ubdf0\ubdf1\ubdf2\ubdf3\ubdf4\ubdf5\ubdf6\ubdf7\ubdf8\ubdf9\ubdfa\ubdfb\ubdfc\ubdfd\ubdfe\ubdff\ube00\ube01\ube02\ube03\ube04\ube05\ube06\ube07\ube08\ube09\ube0a\ube0b\ube0c\ube0d\ube0e\ube0f\ube10\ube11\ube12\ube13\ube14\ube15\ube16\ube17\ube18\ube19\ube1a\ube1b\ube1c\ube1d\ube1e\ube1f\ube20\ube21\ube22\ube23\ube24\ube25\ube26\ube27\ube28\ube29\ube2a\ube2b\ube2c\ube2d\ube2e\ube2f\ube30\ube31\ube32\ube33\ube34\ube35\ube36\ube37\ube38\ube39\ube3a\ube3b\ube3c\ube3d\ube3e\ube3f\ube40\ube41\ube42\ube43\ube44\ube45\ube46\ube47\ube48\ube49\ube4a\ube4b\ube4c\ube4d\ube4e\ube4f\ube50\ube51\ube52\ube53\ube54\ube55\ube56\ube57\ube58\ube59\ube5a\ube5b\ube5c\ube5d\ube5e\ube5f\ube60\ube61\ube62\ube63\ube64\ube65\ube66\ube67\ube68\ube69\ube6a\ube6b\ube6c\ube6d\ube6e\ube6f\ube70\ube71\ube72\ube73\ube74\ube75\ube76\ube77\ube78\ube79\ube7a\ube7b\ube7c\ube7d\ube7e\ube7f\ube80\ube81\ube82\ube83\ube84\ube85\ube86\ube87\ube88\ube89\ube8a\ube8b\ube8c\ube8d\ube8e\ube8f\ube90\ube91\ube92\ube93\ube94\ube95\ube96\ube97\ube98\ube99\ube9a\ube9b\ube9c\ube9d\ube9e\ube9f\ubea0\ubea1\ubea2\ubea3\ubea4\ubea5\ubea6\ubea7\ubea8\ubea9\ubeaa\ubeab\ubeac\ubead\ubeae\ubeaf\ubeb0\ubeb1\ubeb2\ubeb3\ubeb4\ubeb5\ubeb6\ubeb7\ubeb8\ubeb9\ubeba\ubebb\ubebc\ubebd\ubebe\ubebf\ubec0\ubec1\ubec2\ubec3\ubec4\ubec5\ubec6\ubec7\ubec8\ubec9\ubeca\ubecb\ubecc\ubecd\ubece\ubecf\ubed0\ubed1\ubed2\ubed3\ubed4\ubed5\ubed6\ubed7\ubed8\ubed9\ubeda\ubedb\ubedc\ubedd\ubede\ubedf\ubee0\ubee1\ubee2\ubee3\ubee4\ubee5\ubee6\ubee7\ubee8\ubee9\ubeea\ubeeb\ubeec\ubeed\ubeee\ubeef\ubef0\ubef1\ubef2\ubef3\ubef4\ubef5\ubef6\ubef7\ubef8\ubef9\ubefa\ubefb\ubefc\ubefd\ubefe\ubeff\ubf00\ubf01\ubf02\ubf03\ubf04\ubf05\ubf06\ubf07\ubf08\ubf09\ubf0a\ubf0b\ubf0c\ubf0d\ubf0e\ubf0f\ubf10\ubf11\ubf12\ubf13\ubf14\ubf15\ubf16\ubf17\ubf18\ubf19\ubf1a\ubf1b\ubf1c\ubf1d\ubf1e\ubf1f\ubf20\ubf21\ubf22\ubf23\ubf24\ubf25\ubf26\ubf27\ubf28\ubf29\ubf2a\ubf2b\ubf2c\ubf2d\ubf2e\ubf2f\ubf30\ubf31\ubf32\ubf33\ubf34\ubf35\ubf36\ubf37\ubf38\ubf39\ubf3a\ubf3b\ubf3c\ubf3d\ubf3e\ubf3f\ubf40\ubf41\ubf42\ubf43\ubf44\ubf45\ubf46\ubf47\ubf48\ubf49\ubf4a\ubf4b\ubf4c\ubf4d\ubf4e\ubf4f\ubf50\ubf51\ubf52\ubf53\ubf54\ubf55\ubf56\ubf57\ubf58\ubf59\ubf5a\ubf5b\ubf5c\ubf5d\ubf5e\ubf5f\ubf60\ubf61\ubf62\ubf63\ubf64\ubf65\ubf66\ubf67\ubf68\ubf69\ubf6a\ubf6b\ubf6c\ubf6d\ubf6e\ubf6f\ubf70\ubf71\ubf72\ubf73\ubf74\ubf75\ubf76\ubf77\ubf78\ubf79\ubf7a\ubf7b\ubf7c\ubf7d\ubf7e\ubf7f\ubf80\ubf81\ubf82\ubf83\ubf84\ubf85\ubf86\ubf87\ubf88\ubf89\ubf8a\ubf8b\ubf8c\ubf8d\ubf8e\ubf8f\ubf90\ubf91\ubf92\ubf93\ubf94\ubf95\ubf96\ubf97\ubf98\ubf99\ubf9a\ubf9b\ubf9c\ubf9d\ubf9e\ubf9f\ubfa0\ubfa1\ubfa2\ubfa3\ubfa4\ubfa5\ubfa6\ubfa7\ubfa8\ubfa9\ubfaa\ubfab\ubfac\ubfad\ubfae\ubfaf\ubfb0\ubfb1\ubfb2\ubfb3\ubfb4\ubfb5\ubfb6\ubfb7\ubfb8\ubfb9\ubfba\ubfbb\ubfbc\ubfbd\ubfbe\ubfbf\ubfc0\ubfc1\ubfc2\ubfc3\ubfc4\ubfc5\ubfc6\ubfc7\ubfc8\ubfc9\ubfca\ubfcb\ubfcc\ubfcd\ubfce\ubfcf\ubfd0\ubfd1\ubfd2\ubfd3\ubfd4\ubfd5\ubfd6\ubfd7\ubfd8\ubfd9\ubfda\ubfdb\ubfdc\ubfdd\ubfde\ubfdf\ubfe0\ubfe1\ubfe2\ubfe3\ubfe4\ubfe5\ubfe6\ubfe7\ubfe8\ubfe9\ubfea\ubfeb\ubfec\ubfed\ubfee\ubfef\ubff0\ubff1\ubff2\ubff3\ubff4\ubff5\ubff6\ubff7\ubff8\ubff9\ubffa\ubffb\ubffc\ubffd\ubffe\ubfff\uc000\uc001\uc002\uc003\uc004\uc005\uc006\uc007\uc008\uc009\uc00a\uc00b\uc00c\uc00d\uc00e\uc00f\uc010\uc011\uc012\uc013\uc014\uc015\uc016\uc017\uc018\uc019\uc01a\uc01b\uc01c\uc01d\uc01e\uc01f\uc020\uc021\uc022\uc023\uc024\uc025\uc026\uc027\uc028\uc029\uc02a\uc02b\uc02c\uc02d\uc02e\uc02f\uc030\uc031\uc032\uc033\uc034\uc035\uc036\uc037\uc038\uc039\uc03a\uc03b\uc03c\uc03d\uc03e\uc03f\uc040\uc041\uc042\uc043\uc044\uc045\uc046\uc047\uc048\uc049\uc04a\uc04b\uc04c\uc04d\uc04e\uc04f\uc050\uc051\uc052\uc053\uc054\uc055\uc056\uc057\uc058\uc059\uc05a\uc05b\uc05c\uc05d\uc05e\uc05f\uc060\uc061\uc062\uc063\uc064\uc065\uc066\uc067\uc068\uc069\uc06a\uc06b\uc06c\uc06d\uc06e\uc06f\uc070\uc071\uc072\uc073\uc074\uc075\uc076\uc077\uc078\uc079\uc07a\uc07b\uc07c\uc07d\uc07e\uc07f\uc080\uc081\uc082\uc083\uc084\uc085\uc086\uc087\uc088\uc089\uc08a\uc08b\uc08c\uc08d\uc08e\uc08f\uc090\uc091\uc092\uc093\uc094\uc095\uc096\uc097\uc098\uc099\uc09a\uc09b\uc09c\uc09d\uc09e\uc09f\uc0a0\uc0a1\uc0a2\uc0a3\uc0a4\uc0a5\uc0a6\uc0a7\uc0a8\uc0a9\uc0aa\uc0ab\uc0ac\uc0ad\uc0ae\uc0af\uc0b0\uc0b1\uc0b2\uc0b3\uc0b4\uc0b5\uc0b6\uc0b7\uc0b8\uc0b9\uc0ba\uc0bb\uc0bc\uc0bd\uc0be\uc0bf\uc0c0\uc0c1\uc0c2\uc0c3\uc0c4\uc0c5\uc0c6\uc0c7\uc0c8\uc0c9\uc0ca\uc0cb\uc0cc\uc0cd\uc0ce\uc0cf\uc0d0\uc0d1\uc0d2\uc0d3\uc0d4\uc0d5\uc0d6\uc0d7\uc0d8\uc0d9\uc0da\uc0db\uc0dc\uc0dd\uc0de\uc0df\uc0e0\uc0e1\uc0e2\uc0e3\uc0e4\uc0e5\uc0e6\uc0e7\uc0e8\uc0e9\uc0ea\uc0eb\uc0ec\uc0ed\uc0ee\uc0ef\uc0f0\uc0f1\uc0f2\uc0f3\uc0f4\uc0f5\uc0f6\uc0f7\uc0f8\uc0f9\uc0fa\uc0fb\uc0fc\uc0fd\uc0fe\uc0ff\uc100\uc101\uc102\uc103\uc104\uc105\uc106\uc107\uc108\uc109\uc10a\uc10b\uc10c\uc10d\uc10e\uc10f\uc110\uc111\uc112\uc113\uc114\uc115\uc116\uc117\uc118\uc119\uc11a\uc11b\uc11c\uc11d\uc11e\uc11f\uc120\uc121\uc122\uc123\uc124\uc125\uc126\uc127\uc128\uc129\uc12a\uc12b\uc12c\uc12d\uc12e\uc12f\uc130\uc131\uc132\uc133\uc134\uc135\uc136\uc137\uc138\uc139\uc13a\uc13b\uc13c\uc13d\uc13e\uc13f\uc140\uc141\uc142\uc143\uc144\uc145\uc146\uc147\uc148\uc149\uc14a\uc14b\uc14c\uc14d\uc14e\uc14f\uc150\uc151\uc152\uc153\uc154\uc155\uc156\uc157\uc158\uc159\uc15a\uc15b\uc15c\uc15d\uc15e\uc15f\uc160\uc161\uc162\uc163\uc164\uc165\uc166\uc167\uc168\uc169\uc16a\uc16b\uc16c\uc16d\uc16e\uc16f\uc170\uc171\uc172\uc173\uc174\uc175\uc176\uc177\uc178\uc179\uc17a\uc17b\uc17c\uc17d\uc17e\uc17f\uc180\uc181\uc182\uc183\uc184\uc185\uc186\uc187\uc188\uc189\uc18a\uc18b\uc18c\uc18d\uc18e\uc18f\uc190\uc191\uc192\uc193\uc194\uc195\uc196\uc197\uc198\uc199\uc19a\uc19b\uc19c\uc19d\uc19e\uc19f\uc1a0\uc1a1\uc1a2\uc1a3\uc1a4\uc1a5\uc1a6\uc1a7\uc1a8\uc1a9\uc1aa\uc1ab\uc1ac\uc1ad\uc1ae\uc1af\uc1b0\uc1b1\uc1b2\uc1b3\uc1b4\uc1b5\uc1b6\uc1b7\uc1b8\uc1b9\uc1ba\uc1bb\uc1bc\uc1bd\uc1be\uc1bf\uc1c0\uc1c1\uc1c2\uc1c3\uc1c4\uc1c5\uc1c6\uc1c7\uc1c8\uc1c9\uc1ca\uc1cb\uc1cc\uc1cd\uc1ce\uc1cf\uc1d0\uc1d1\uc1d2\uc1d3\uc1d4\uc1d5\uc1d6\uc1d7\uc1d8\uc1d9\uc1da\uc1db\uc1dc\uc1dd\uc1de\uc1df\uc1e0\uc1e1\uc1e2\uc1e3\uc1e4\uc1e5\uc1e6\uc1e7\uc1e8\uc1e9\uc1ea\uc1eb\uc1ec\uc1ed\uc1ee\uc1ef\uc1f0\uc1f1\uc1f2\uc1f3\uc1f4\uc1f5\uc1f6\uc1f7\uc1f8\uc1f9\uc1fa\uc1fb\uc1fc\uc1fd\uc1fe\uc1ff\uc200\uc201\uc202\uc203\uc204\uc205\uc206\uc207\uc208\uc209\uc20a\uc20b\uc20c\uc20d\uc20e\uc20f\uc210\uc211\uc212\uc213\uc214\uc215\uc216\uc217\uc218\uc219\uc21a\uc21b\uc21c\uc21d\uc21e\uc21f\uc220\uc221\uc222\uc223\uc224\uc225\uc226\uc227\uc228\uc229\uc22a\uc22b\uc22c\uc22d\uc22e\uc22f\uc230\uc231\uc232\uc233\uc234\uc235\uc236\uc237\uc238\uc239\uc23a\uc23b\uc23c\uc23d\uc23e\uc23f\uc240\uc241\uc242\uc243\uc244\uc245\uc246\uc247\uc248\uc249\uc24a\uc24b\uc24c\uc24d\uc24e\uc24f\uc250\uc251\uc252\uc253\uc254\uc255\uc256\uc257\uc258\uc259\uc25a\uc25b\uc25c\uc25d\uc25e\uc25f\uc260\uc261\uc262\uc263\uc264\uc265\uc266\uc267\uc268\uc269\uc26a\uc26b\uc26c\uc26d\uc26e\uc26f\uc270\uc271\uc272\uc273\uc274\uc275\uc276\uc277\uc278\uc279\uc27a\uc27b\uc27c\uc27d\uc27e\uc27f\uc280\uc281\uc282\uc283\uc284\uc285\uc286\uc287\uc288\uc289\uc28a\uc28b\uc28c\uc28d\uc28e\uc28f\uc290\uc291\uc292\uc293\uc294\uc295\uc296\uc297\uc298\uc299\uc29a\uc29b\uc29c\uc29d\uc29e\uc29f\uc2a0\uc2a1\uc2a2\uc2a3\uc2a4\uc2a5\uc2a6\uc2a7\uc2a8\uc2a9\uc2aa\uc2ab\uc2ac\uc2ad\uc2ae\uc2af\uc2b0\uc2b1\uc2b2\uc2b3\uc2b4\uc2b5\uc2b6\uc2b7\uc2b8\uc2b9\uc2ba\uc2bb\uc2bc\uc2bd\uc2be\uc2bf\uc2c0\uc2c1\uc2c2\uc2c3\uc2c4\uc2c5\uc2c6\uc2c7\uc2c8\uc2c9\uc2ca\uc2cb\uc2cc\uc2cd\uc2ce\uc2cf\uc2d0\uc2d1\uc2d2\uc2d3\uc2d4\uc2d5\uc2d6\uc2d7\uc2d8\uc2d9\uc2da\uc2db\uc2dc\uc2dd\uc2de\uc2df\uc2e0\uc2e1\uc2e2\uc2e3\uc2e4\uc2e5\uc2e6\uc2e7\uc2e8\uc2e9\uc2ea\uc2eb\uc2ec\uc2ed\uc2ee\uc2ef\uc2f0\uc2f1\uc2f2\uc2f3\uc2f4\uc2f5\uc2f6\uc2f7\uc2f8\uc2f9\uc2fa\uc2fb\uc2fc\uc2fd\uc2fe\uc2ff\uc300\uc301\uc302\uc303\uc304\uc305\uc306\uc307\uc308\uc309\uc30a\uc30b\uc30c\uc30d\uc30e\uc30f\uc310\uc311\uc312\uc313\uc314\uc315\uc316\uc317\uc318\uc319\uc31a\uc31b\uc31c\uc31d\uc31e\uc31f\uc320\uc321\uc322\uc323\uc324\uc325\uc326\uc327\uc328\uc329\uc32a\uc32b\uc32c\uc32d\uc32e\uc32f\uc330\uc331\uc332\uc333\uc334\uc335\uc336\uc337\uc338\uc339\uc33a\uc33b\uc33c\uc33d\uc33e\uc33f\uc340\uc341\uc342\uc343\uc344\uc345\uc346\uc347\uc348\uc349\uc34a\uc34b\uc34c\uc34d\uc34e\uc34f\uc350\uc351\uc352\uc353\uc354\uc355\uc356\uc357\uc358\uc359\uc35a\uc35b\uc35c\uc35d\uc35e\uc35f\uc360\uc361\uc362\uc363\uc364\uc365\uc366\uc367\uc368\uc369\uc36a\uc36b\uc36c\uc36d\uc36e\uc36f\uc370\uc371\uc372\uc373\uc374\uc375\uc376\uc377\uc378\uc379\uc37a\uc37b\uc37c\uc37d\uc37e\uc37f\uc380\uc381\uc382\uc383\uc384\uc385\uc386\uc387\uc388\uc389\uc38a\uc38b\uc38c\uc38d\uc38e\uc38f\uc390\uc391\uc392\uc393\uc394\uc395\uc396\uc397\uc398\uc399\uc39a\uc39b\uc39c\uc39d\uc39e\uc39f\uc3a0\uc3a1\uc3a2\uc3a3\uc3a4\uc3a5\uc3a6\uc3a7\uc3a8\uc3a9\uc3aa\uc3ab\uc3ac\uc3ad\uc3ae\uc3af\uc3b0\uc3b1\uc3b2\uc3b3\uc3b4\uc3b5\uc3b6\uc3b7\uc3b8\uc3b9\uc3ba\uc3bb\uc3bc\uc3bd\uc3be\uc3bf\uc3c0\uc3c1\uc3c2\uc3c3\uc3c4\uc3c5\uc3c6\uc3c7\uc3c8\uc3c9\uc3ca\uc3cb\uc3cc\uc3cd\uc3ce\uc3cf\uc3d0\uc3d1\uc3d2\uc3d3\uc3d4\uc3d5\uc3d6\uc3d7\uc3d8\uc3d9\uc3da\uc3db\uc3dc\uc3dd\uc3de\uc3df\uc3e0\uc3e1\uc3e2\uc3e3\uc3e4\uc3e5\uc3e6\uc3e7\uc3e8\uc3e9\uc3ea\uc3eb\uc3ec\uc3ed\uc3ee\uc3ef\uc3f0\uc3f1\uc3f2\uc3f3\uc3f4\uc3f5\uc3f6\uc3f7\uc3f8\uc3f9\uc3fa\uc3fb\uc3fc\uc3fd\uc3fe\uc3ff\uc400\uc401\uc402\uc403\uc404\uc405\uc406\uc407\uc408\uc409\uc40a\uc40b\uc40c\uc40d\uc40e\uc40f\uc410\uc411\uc412\uc413\uc414\uc415\uc416\uc417\uc418\uc419\uc41a\uc41b\uc41c\uc41d\uc41e\uc41f\uc420\uc421\uc422\uc423\uc424\uc425\uc426\uc427\uc428\uc429\uc42a\uc42b\uc42c\uc42d\uc42e\uc42f\uc430\uc431\uc432\uc433\uc434\uc435\uc436\uc437\uc438\uc439\uc43a\uc43b\uc43c\uc43d\uc43e\uc43f\uc440\uc441\uc442\uc443\uc444\uc445\uc446\uc447\uc448\uc449\uc44a\uc44b\uc44c\uc44d\uc44e\uc44f\uc450\uc451\uc452\uc453\uc454\uc455\uc456\uc457\uc458\uc459\uc45a\uc45b\uc45c\uc45d\uc45e\uc45f\uc460\uc461\uc462\uc463\uc464\uc465\uc466\uc467\uc468\uc469\uc46a\uc46b\uc46c\uc46d\uc46e\uc46f\uc470\uc471\uc472\uc473\uc474\uc475\uc476\uc477\uc478\uc479\uc47a\uc47b\uc47c\uc47d\uc47e\uc47f\uc480\uc481\uc482\uc483\uc484\uc485\uc486\uc487\uc488\uc489\uc48a\uc48b\uc48c\uc48d\uc48e\uc48f\uc490\uc491\uc492\uc493\uc494\uc495\uc496\uc497\uc498\uc499\uc49a\uc49b\uc49c\uc49d\uc49e\uc49f\uc4a0\uc4a1\uc4a2\uc4a3\uc4a4\uc4a5\uc4a6\uc4a7\uc4a8\uc4a9\uc4aa\uc4ab\uc4ac\uc4ad\uc4ae\uc4af\uc4b0\uc4b1\uc4b2\uc4b3\uc4b4\uc4b5\uc4b6\uc4b7\uc4b8\uc4b9\uc4ba\uc4bb\uc4bc\uc4bd\uc4be\uc4bf\uc4c0\uc4c1\uc4c2\uc4c3\uc4c4\uc4c5\uc4c6\uc4c7\uc4c8\uc4c9\uc4ca\uc4cb\uc4cc\uc4cd\uc4ce\uc4cf\uc4d0\uc4d1\uc4d2\uc4d3\uc4d4\uc4d5\uc4d6\uc4d7\uc4d8\uc4d9\uc4da\uc4db\uc4dc\uc4dd\uc4de\uc4df\uc4e0\uc4e1\uc4e2\uc4e3\uc4e4\uc4e5\uc4e6\uc4e7\uc4e8\uc4e9\uc4ea\uc4eb\uc4ec\uc4ed\uc4ee\uc4ef\uc4f0\uc4f1\uc4f2\uc4f3\uc4f4\uc4f5\uc4f6\uc4f7\uc4f8\uc4f9\uc4fa\uc4fb\uc4fc\uc4fd\uc4fe\uc4ff\uc500\uc501\uc502\uc503\uc504\uc505\uc506\uc507\uc508\uc509\uc50a\uc50b\uc50c\uc50d\uc50e\uc50f\uc510\uc511\uc512\uc513\uc514\uc515\uc516\uc517\uc518\uc519\uc51a\uc51b\uc51c\uc51d\uc51e\uc51f\uc520\uc521\uc522\uc523\uc524\uc525\uc526\uc527\uc528\uc529\uc52a\uc52b\uc52c\uc52d\uc52e\uc52f\uc530\uc531\uc532\uc533\uc534\uc535\uc536\uc537\uc538\uc539\uc53a\uc53b\uc53c\uc53d\uc53e\uc53f\uc540\uc541\uc542\uc543\uc544\uc545\uc546\uc547\uc548\uc549\uc54a\uc54b\uc54c\uc54d\uc54e\uc54f\uc550\uc551\uc552\uc553\uc554\uc555\uc556\uc557\uc558\uc559\uc55a\uc55b\uc55c\uc55d\uc55e\uc55f\uc560\uc561\uc562\uc563\uc564\uc565\uc566\uc567\uc568\uc569\uc56a\uc56b\uc56c\uc56d\uc56e\uc56f\uc570\uc571\uc572\uc573\uc574\uc575\uc576\uc577\uc578\uc579\uc57a\uc57b\uc57c\uc57d\uc57e\uc57f\uc580\uc581\uc582\uc583\uc584\uc585\uc586\uc587\uc588\uc589\uc58a\uc58b\uc58c\uc58d\uc58e\uc58f\uc590\uc591\uc592\uc593\uc594\uc595\uc596\uc597\uc598\uc599\uc59a\uc59b\uc59c\uc59d\uc59e\uc59f\uc5a0\uc5a1\uc5a2\uc5a3\uc5a4\uc5a5\uc5a6\uc5a7\uc5a8\uc5a9\uc5aa\uc5ab\uc5ac\uc5ad\uc5ae\uc5af\uc5b0\uc5b1\uc5b2\uc5b3\uc5b4\uc5b5\uc5b6\uc5b7\uc5b8\uc5b9\uc5ba\uc5bb\uc5bc\uc5bd\uc5be\uc5bf\uc5c0\uc5c1\uc5c2\uc5c3\uc5c4\uc5c5\uc5c6\uc5c7\uc5c8\uc5c9\uc5ca\uc5cb\uc5cc\uc5cd\uc5ce\uc5cf\uc5d0\uc5d1\uc5d2\uc5d3\uc5d4\uc5d5\uc5d6\uc5d7\uc5d8\uc5d9\uc5da\uc5db\uc5dc\uc5dd\uc5de\uc5df\uc5e0\uc5e1\uc5e2\uc5e3\uc5e4\uc5e5\uc5e6\uc5e7\uc5e8\uc5e9\uc5ea\uc5eb\uc5ec\uc5ed\uc5ee\uc5ef\uc5f0\uc5f1\uc5f2\uc5f3\uc5f4\uc5f5\uc5f6\uc5f7\uc5f8\uc5f9\uc5fa\uc5fb\uc5fc\uc5fd\uc5fe\uc5ff\uc600\uc601\uc602\uc603\uc604\uc605\uc606\uc607\uc608\uc609\uc60a\uc60b\uc60c\uc60d\uc60e\uc60f\uc610\uc611\uc612\uc613\uc614\uc615\uc616\uc617\uc618\uc619\uc61a\uc61b\uc61c\uc61d\uc61e\uc61f\uc620\uc621\uc622\uc623\uc624\uc625\uc626\uc627\uc628\uc629\uc62a\uc62b\uc62c\uc62d\uc62e\uc62f\uc630\uc631\uc632\uc633\uc634\uc635\uc636\uc637\uc638\uc639\uc63a\uc63b\uc63c\uc63d\uc63e\uc63f\uc640\uc641\uc642\uc643\uc644\uc645\uc646\uc647\uc648\uc649\uc64a\uc64b\uc64c\uc64d\uc64e\uc64f\uc650\uc651\uc652\uc653\uc654\uc655\uc656\uc657\uc658\uc659\uc65a\uc65b\uc65c\uc65d\uc65e\uc65f\uc660\uc661\uc662\uc663\uc664\uc665\uc666\uc667\uc668\uc669\uc66a\uc66b\uc66c\uc66d\uc66e\uc66f\uc670\uc671\uc672\uc673\uc674\uc675\uc676\uc677\uc678\uc679\uc67a\uc67b\uc67c\uc67d\uc67e\uc67f\uc680\uc681\uc682\uc683\uc684\uc685\uc686\uc687\uc688\uc689\uc68a\uc68b\uc68c\uc68d\uc68e\uc68f\uc690\uc691\uc692\uc693\uc694\uc695\uc696\uc697\uc698\uc699\uc69a\uc69b\uc69c\uc69d\uc69e\uc69f\uc6a0\uc6a1\uc6a2\uc6a3\uc6a4\uc6a5\uc6a6\uc6a7\uc6a8\uc6a9\uc6aa\uc6ab\uc6ac\uc6ad\uc6ae\uc6af\uc6b0\uc6b1\uc6b2\uc6b3\uc6b4\uc6b5\uc6b6\uc6b7\uc6b8\uc6b9\uc6ba\uc6bb\uc6bc\uc6bd\uc6be\uc6bf\uc6c0\uc6c1\uc6c2\uc6c3\uc6c4\uc6c5\uc6c6\uc6c7\uc6c8\uc6c9\uc6ca\uc6cb\uc6cc\uc6cd\uc6ce\uc6cf\uc6d0\uc6d1\uc6d2\uc6d3\uc6d4\uc6d5\uc6d6\uc6d7\uc6d8\uc6d9\uc6da\uc6db\uc6dc\uc6dd\uc6de\uc6df\uc6e0\uc6e1\uc6e2\uc6e3\uc6e4\uc6e5\uc6e6\uc6e7\uc6e8\uc6e9\uc6ea\uc6eb\uc6ec\uc6ed\uc6ee\uc6ef\uc6f0\uc6f1\uc6f2\uc6f3\uc6f4\uc6f5\uc6f6\uc6f7\uc6f8\uc6f9\uc6fa\uc6fb\uc6fc\uc6fd\uc6fe\uc6ff\uc700\uc701\uc702\uc703\uc704\uc705\uc706\uc707\uc708\uc709\uc70a\uc70b\uc70c\uc70d\uc70e\uc70f\uc710\uc711\uc712\uc713\uc714\uc715\uc716\uc717\uc718\uc719\uc71a\uc71b\uc71c\uc71d\uc71e\uc71f\uc720\uc721\uc722\uc723\uc724\uc725\uc726\uc727\uc728\uc729\uc72a\uc72b\uc72c\uc72d\uc72e\uc72f\uc730\uc731\uc732\uc733\uc734\uc735\uc736\uc737\uc738\uc739\uc73a\uc73b\uc73c\uc73d\uc73e\uc73f\uc740\uc741\uc742\uc743\uc744\uc745\uc746\uc747\uc748\uc749\uc74a\uc74b\uc74c\uc74d\uc74e\uc74f\uc750\uc751\uc752\uc753\uc754\uc755\uc756\uc757\uc758\uc759\uc75a\uc75b\uc75c\uc75d\uc75e\uc75f\uc760\uc761\uc762\uc763\uc764\uc765\uc766\uc767\uc768\uc769\uc76a\uc76b\uc76c\uc76d\uc76e\uc76f\uc770\uc771\uc772\uc773\uc774\uc775\uc776\uc777\uc778\uc779\uc77a\uc77b\uc77c\uc77d\uc77e\uc77f\uc780\uc781\uc782\uc783\uc784\uc785\uc786\uc787\uc788\uc789\uc78a\uc78b\uc78c\uc78d\uc78e\uc78f\uc790\uc791\uc792\uc793\uc794\uc795\uc796\uc797\uc798\uc799\uc79a\uc79b\uc79c\uc79d\uc79e\uc79f\uc7a0\uc7a1\uc7a2\uc7a3\uc7a4\uc7a5\uc7a6\uc7a7\uc7a8\uc7a9\uc7aa\uc7ab\uc7ac\uc7ad\uc7ae\uc7af\uc7b0\uc7b1\uc7b2\uc7b3\uc7b4\uc7b5\uc7b6\uc7b7\uc7b8\uc7b9\uc7ba\uc7bb\uc7bc\uc7bd\uc7be\uc7bf\uc7c0\uc7c1\uc7c2\uc7c3\uc7c4\uc7c5\uc7c6\uc7c7\uc7c8\uc7c9\uc7ca\uc7cb\uc7cc\uc7cd\uc7ce\uc7cf\uc7d0\uc7d1\uc7d2\uc7d3\uc7d4\uc7d5\uc7d6\uc7d7\uc7d8\uc7d9\uc7da\uc7db\uc7dc\uc7dd\uc7de\uc7df\uc7e0\uc7e1\uc7e2\uc7e3\uc7e4\uc7e5\uc7e6\uc7e7\uc7e8\uc7e9\uc7ea\uc7eb\uc7ec\uc7ed\uc7ee\uc7ef\uc7f0\uc7f1\uc7f2\uc7f3\uc7f4\uc7f5\uc7f6\uc7f7\uc7f8\uc7f9\uc7fa\uc7fb\uc7fc\uc7fd\uc7fe\uc7ff\uc800\uc801\uc802\uc803\uc804\uc805\uc806\uc807\uc808\uc809\uc80a\uc80b\uc80c\uc80d\uc80e\uc80f\uc810\uc811\uc812\uc813\uc814\uc815\uc816\uc817\uc818\uc819\uc81a\uc81b\uc81c\uc81d\uc81e\uc81f\uc820\uc821\uc822\uc823\uc824\uc825\uc826\uc827\uc828\uc829\uc82a\uc82b\uc82c\uc82d\uc82e\uc82f\uc830\uc831\uc832\uc833\uc834\uc835\uc836\uc837\uc838\uc839\uc83a\uc83b\uc83c\uc83d\uc83e\uc83f\uc840\uc841\uc842\uc843\uc844\uc845\uc846\uc847\uc848\uc849\uc84a\uc84b\uc84c\uc84d\uc84e\uc84f\uc850\uc851\uc852\uc853\uc854\uc855\uc856\uc857\uc858\uc859\uc85a\uc85b\uc85c\uc85d\uc85e\uc85f\uc860\uc861\uc862\uc863\uc864\uc865\uc866\uc867\uc868\uc869\uc86a\uc86b\uc86c\uc86d\uc86e\uc86f\uc870\uc871\uc872\uc873\uc874\uc875\uc876\uc877\uc878\uc879\uc87a\uc87b\uc87c\uc87d\uc87e\uc87f\uc880\uc881\uc882\uc883\uc884\uc885\uc886\uc887\uc888\uc889\uc88a\uc88b\uc88c\uc88d\uc88e\uc88f\uc890\uc891\uc892\uc893\uc894\uc895\uc896\uc897\uc898\uc899\uc89a\uc89b\uc89c\uc89d\uc89e\uc89f\uc8a0\uc8a1\uc8a2\uc8a3\uc8a4\uc8a5\uc8a6\uc8a7\uc8a8\uc8a9\uc8aa\uc8ab\uc8ac\uc8ad\uc8ae\uc8af\uc8b0\uc8b1\uc8b2\uc8b3\uc8b4\uc8b5\uc8b6\uc8b7\uc8b8\uc8b9\uc8ba\uc8bb\uc8bc\uc8bd\uc8be\uc8bf\uc8c0\uc8c1\uc8c2\uc8c3\uc8c4\uc8c5\uc8c6\uc8c7\uc8c8\uc8c9\uc8ca\uc8cb\uc8cc\uc8cd\uc8ce\uc8cf\uc8d0\uc8d1\uc8d2\uc8d3\uc8d4\uc8d5\uc8d6\uc8d7\uc8d8\uc8d9\uc8da\uc8db\uc8dc\uc8dd\uc8de\uc8df\uc8e0\uc8e1\uc8e2\uc8e3\uc8e4\uc8e5\uc8e6\uc8e7\uc8e8\uc8e9\uc8ea\uc8eb\uc8ec\uc8ed\uc8ee\uc8ef\uc8f0\uc8f1\uc8f2\uc8f3\uc8f4\uc8f5\uc8f6\uc8f7\uc8f8\uc8f9\uc8fa\uc8fb\uc8fc\uc8fd\uc8fe\uc8ff\uc900\uc901\uc902\uc903\uc904\uc905\uc906\uc907\uc908\uc909\uc90a\uc90b\uc90c\uc90d\uc90e\uc90f\uc910\uc911\uc912\uc913\uc914\uc915\uc916\uc917\uc918\uc919\uc91a\uc91b\uc91c\uc91d\uc91e\uc91f\uc920\uc921\uc922\uc923\uc924\uc925\uc926\uc927\uc928\uc929\uc92a\uc92b\uc92c\uc92d\uc92e\uc92f\uc930\uc931\uc932\uc933\uc934\uc935\uc936\uc937\uc938\uc939\uc93a\uc93b\uc93c\uc93d\uc93e\uc93f\uc940\uc941\uc942\uc943\uc944\uc945\uc946\uc947\uc948\uc949\uc94a\uc94b\uc94c\uc94d\uc94e\uc94f\uc950\uc951\uc952\uc953\uc954\uc955\uc956\uc957\uc958\uc959\uc95a\uc95b\uc95c\uc95d\uc95e\uc95f\uc960\uc961\uc962\uc963\uc964\uc965\uc966\uc967\uc968\uc969\uc96a\uc96b\uc96c\uc96d\uc96e\uc96f\uc970\uc971\uc972\uc973\uc974\uc975\uc976\uc977\uc978\uc979\uc97a\uc97b\uc97c\uc97d\uc97e\uc97f\uc980\uc981\uc982\uc983\uc984\uc985\uc986\uc987\uc988\uc989\uc98a\uc98b\uc98c\uc98d\uc98e\uc98f\uc990\uc991\uc992\uc993\uc994\uc995\uc996\uc997\uc998\uc999\uc99a\uc99b\uc99c\uc99d\uc99e\uc99f\uc9a0\uc9a1\uc9a2\uc9a3\uc9a4\uc9a5\uc9a6\uc9a7\uc9a8\uc9a9\uc9aa\uc9ab\uc9ac\uc9ad\uc9ae\uc9af\uc9b0\uc9b1\uc9b2\uc9b3\uc9b4\uc9b5\uc9b6\uc9b7\uc9b8\uc9b9\uc9ba\uc9bb\uc9bc\uc9bd\uc9be\uc9bf\uc9c0\uc9c1\uc9c2\uc9c3\uc9c4\uc9c5\uc9c6\uc9c7\uc9c8\uc9c9\uc9ca\uc9cb\uc9cc\uc9cd\uc9ce\uc9cf\uc9d0\uc9d1\uc9d2\uc9d3\uc9d4\uc9d5\uc9d6\uc9d7\uc9d8\uc9d9\uc9da\uc9db\uc9dc\uc9dd\uc9de\uc9df\uc9e0\uc9e1\uc9e2\uc9e3\uc9e4\uc9e5\uc9e6\uc9e7\uc9e8\uc9e9\uc9ea\uc9eb\uc9ec\uc9ed\uc9ee\uc9ef\uc9f0\uc9f1\uc9f2\uc9f3\uc9f4\uc9f5\uc9f6\uc9f7\uc9f8\uc9f9\uc9fa\uc9fb\uc9fc\uc9fd\uc9fe\uc9ff\uca00\uca01\uca02\uca03\uca04\uca05\uca06\uca07\uca08\uca09\uca0a\uca0b\uca0c\uca0d\uca0e\uca0f\uca10\uca11\uca12\uca13\uca14\uca15\uca16\uca17\uca18\uca19\uca1a\uca1b\uca1c\uca1d\uca1e\uca1f\uca20\uca21\uca22\uca23\uca24\uca25\uca26\uca27\uca28\uca29\uca2a\uca2b\uca2c\uca2d\uca2e\uca2f\uca30\uca31\uca32\uca33\uca34\uca35\uca36\uca37\uca38\uca39\uca3a\uca3b\uca3c\uca3d\uca3e\uca3f\uca40\uca41\uca42\uca43\uca44\uca45\uca46\uca47\uca48\uca49\uca4a\uca4b\uca4c\uca4d\uca4e\uca4f\uca50\uca51\uca52\uca53\uca54\uca55\uca56\uca57\uca58\uca59\uca5a\uca5b\uca5c\uca5d\uca5e\uca5f\uca60\uca61\uca62\uca63\uca64\uca65\uca66\uca67\uca68\uca69\uca6a\uca6b\uca6c\uca6d\uca6e\uca6f\uca70\uca71\uca72\uca73\uca74\uca75\uca76\uca77\uca78\uca79\uca7a\uca7b\uca7c\uca7d\uca7e\uca7f\uca80\uca81\uca82\uca83\uca84\uca85\uca86\uca87\uca88\uca89\uca8a\uca8b\uca8c\uca8d\uca8e\uca8f\uca90\uca91\uca92\uca93\uca94\uca95\uca96\uca97\uca98\uca99\uca9a\uca9b\uca9c\uca9d\uca9e\uca9f\ucaa0\ucaa1\ucaa2\ucaa3\ucaa4\ucaa5\ucaa6\ucaa7\ucaa8\ucaa9\ucaaa\ucaab\ucaac\ucaad\ucaae\ucaaf\ucab0\ucab1\ucab2\ucab3\ucab4\ucab5\ucab6\ucab7\ucab8\ucab9\ucaba\ucabb\ucabc\ucabd\ucabe\ucabf\ucac0\ucac1\ucac2\ucac3\ucac4\ucac5\ucac6\ucac7\ucac8\ucac9\ucaca\ucacb\ucacc\ucacd\ucace\ucacf\ucad0\ucad1\ucad2\ucad3\ucad4\ucad5\ucad6\ucad7\ucad8\ucad9\ucada\ucadb\ucadc\ucadd\ucade\ucadf\ucae0\ucae1\ucae2\ucae3\ucae4\ucae5\ucae6\ucae7\ucae8\ucae9\ucaea\ucaeb\ucaec\ucaed\ucaee\ucaef\ucaf0\ucaf1\ucaf2\ucaf3\ucaf4\ucaf5\ucaf6\ucaf7\ucaf8\ucaf9\ucafa\ucafb\ucafc\ucafd\ucafe\ucaff\ucb00\ucb01\ucb02\ucb03\ucb04\ucb05\ucb06\ucb07\ucb08\ucb09\ucb0a\ucb0b\ucb0c\ucb0d\ucb0e\ucb0f\ucb10\ucb11\ucb12\ucb13\ucb14\ucb15\ucb16\ucb17\ucb18\ucb19\ucb1a\ucb1b\ucb1c\ucb1d\ucb1e\ucb1f\ucb20\ucb21\ucb22\ucb23\ucb24\ucb25\ucb26\ucb27\ucb28\ucb29\ucb2a\ucb2b\ucb2c\ucb2d\ucb2e\ucb2f\ucb30\ucb31\ucb32\ucb33\ucb34\ucb35\ucb36\ucb37\ucb38\ucb39\ucb3a\ucb3b\ucb3c\ucb3d\ucb3e\ucb3f\ucb40\ucb41\ucb42\ucb43\ucb44\ucb45\ucb46\ucb47\ucb48\ucb49\ucb4a\ucb4b\ucb4c\ucb4d\ucb4e\ucb4f\ucb50\ucb51\ucb52\ucb53\ucb54\ucb55\ucb56\ucb57\ucb58\ucb59\ucb5a\ucb5b\ucb5c\ucb5d\ucb5e\ucb5f\ucb60\ucb61\ucb62\ucb63\ucb64\ucb65\ucb66\ucb67\ucb68\ucb69\ucb6a\ucb6b\ucb6c\ucb6d\ucb6e\ucb6f\ucb70\ucb71\ucb72\ucb73\ucb74\ucb75\ucb76\ucb77\ucb78\ucb79\ucb7a\ucb7b\ucb7c\ucb7d\ucb7e\ucb7f\ucb80\ucb81\ucb82\ucb83\ucb84\ucb85\ucb86\ucb87\ucb88\ucb89\ucb8a\ucb8b\ucb8c\ucb8d\ucb8e\ucb8f\ucb90\ucb91\ucb92\ucb93\ucb94\ucb95\ucb96\ucb97\ucb98\ucb99\ucb9a\ucb9b\ucb9c\ucb9d\ucb9e\ucb9f\ucba0\ucba1\ucba2\ucba3\ucba4\ucba5\ucba6\ucba7\ucba8\ucba9\ucbaa\ucbab\ucbac\ucbad\ucbae\ucbaf\ucbb0\ucbb1\ucbb2\ucbb3\ucbb4\ucbb5\ucbb6\ucbb7\ucbb8\ucbb9\ucbba\ucbbb\ucbbc\ucbbd\ucbbe\ucbbf\ucbc0\ucbc1\ucbc2\ucbc3\ucbc4\ucbc5\ucbc6\ucbc7\ucbc8\ucbc9\ucbca\ucbcb\ucbcc\ucbcd\ucbce\ucbcf\ucbd0\ucbd1\ucbd2\ucbd3\ucbd4\ucbd5\ucbd6\ucbd7\ucbd8\ucbd9\ucbda\ucbdb\ucbdc\ucbdd\ucbde\ucbdf\ucbe0\ucbe1\ucbe2\ucbe3\ucbe4\ucbe5\ucbe6\ucbe7\ucbe8\ucbe9\ucbea\ucbeb\ucbec\ucbed\ucbee\ucbef\ucbf0\ucbf1\ucbf2\ucbf3\ucbf4\ucbf5\ucbf6\ucbf7\ucbf8\ucbf9\ucbfa\ucbfb\ucbfc\ucbfd\ucbfe\ucbff\ucc00\ucc01\ucc02\ucc03\ucc04\ucc05\ucc06\ucc07\ucc08\ucc09\ucc0a\ucc0b\ucc0c\ucc0d\ucc0e\ucc0f\ucc10\ucc11\ucc12\ucc13\ucc14\ucc15\ucc16\ucc17\ucc18\ucc19\ucc1a\ucc1b\ucc1c\ucc1d\ucc1e\ucc1f\ucc20\ucc21\ucc22\ucc23\ucc24\ucc25\ucc26\ucc27\ucc28\ucc29\ucc2a\ucc2b\ucc2c\ucc2d\ucc2e\ucc2f\ucc30\ucc31\ucc32\ucc33\ucc34\ucc35\ucc36\ucc37\ucc38\ucc39\ucc3a\ucc3b\ucc3c\ucc3d\ucc3e\ucc3f\ucc40\ucc41\ucc42\ucc43\ucc44\ucc45\ucc46\ucc47\ucc48\ucc49\ucc4a\ucc4b\ucc4c\ucc4d\ucc4e\ucc4f\ucc50\ucc51\ucc52\ucc53\ucc54\ucc55\ucc56\ucc57\ucc58\ucc59\ucc5a\ucc5b\ucc5c\ucc5d\ucc5e\ucc5f\ucc60\ucc61\ucc62\ucc63\ucc64\ucc65\ucc66\ucc67\ucc68\ucc69\ucc6a\ucc6b\ucc6c\ucc6d\ucc6e\ucc6f\ucc70\ucc71\ucc72\ucc73\ucc74\ucc75\ucc76\ucc77\ucc78\ucc79\ucc7a\ucc7b\ucc7c\ucc7d\ucc7e\ucc7f\ucc80\ucc81\ucc82\ucc83\ucc84\ucc85\ucc86\ucc87\ucc88\ucc89\ucc8a\ucc8b\ucc8c\ucc8d\ucc8e\ucc8f\ucc90\ucc91\ucc92\ucc93\ucc94\ucc95\ucc96\ucc97\ucc98\ucc99\ucc9a\ucc9b\ucc9c\ucc9d\ucc9e\ucc9f\ucca0\ucca1\ucca2\ucca3\ucca4\ucca5\ucca6\ucca7\ucca8\ucca9\uccaa\uccab\uccac\uccad\uccae\uccaf\uccb0\uccb1\uccb2\uccb3\uccb4\uccb5\uccb6\uccb7\uccb8\uccb9\uccba\uccbb\uccbc\uccbd\uccbe\uccbf\uccc0\uccc1\uccc2\uccc3\uccc4\uccc5\uccc6\uccc7\uccc8\uccc9\uccca\ucccb\ucccc\ucccd\uccce\ucccf\uccd0\uccd1\uccd2\uccd3\uccd4\uccd5\uccd6\uccd7\uccd8\uccd9\uccda\uccdb\uccdc\uccdd\uccde\uccdf\ucce0\ucce1\ucce2\ucce3\ucce4\ucce5\ucce6\ucce7\ucce8\ucce9\uccea\ucceb\uccec\ucced\uccee\uccef\uccf0\uccf1\uccf2\uccf3\uccf4\uccf5\uccf6\uccf7\uccf8\uccf9\uccfa\uccfb\uccfc\uccfd\uccfe\uccff\ucd00\ucd01\ucd02\ucd03\ucd04\ucd05\ucd06\ucd07\ucd08\ucd09\ucd0a\ucd0b\ucd0c\ucd0d\ucd0e\ucd0f\ucd10\ucd11\ucd12\ucd13\ucd14\ucd15\ucd16\ucd17\ucd18\ucd19\ucd1a\ucd1b\ucd1c\ucd1d\ucd1e\ucd1f\ucd20\ucd21\ucd22\ucd23\ucd24\ucd25\ucd26\ucd27\ucd28\ucd29\ucd2a\ucd2b\ucd2c\ucd2d\ucd2e\ucd2f\ucd30\ucd31\ucd32\ucd33\ucd34\ucd35\ucd36\ucd37\ucd38\ucd39\ucd3a\ucd3b\ucd3c\ucd3d\ucd3e\ucd3f\ucd40\ucd41\ucd42\ucd43\ucd44\ucd45\ucd46\ucd47\ucd48\ucd49\ucd4a\ucd4b\ucd4c\ucd4d\ucd4e\ucd4f\ucd50\ucd51\ucd52\ucd53\ucd54\ucd55\ucd56\ucd57\ucd58\ucd59\ucd5a\ucd5b\ucd5c\ucd5d\ucd5e\ucd5f\ucd60\ucd61\ucd62\ucd63\ucd64\ucd65\ucd66\ucd67\ucd68\ucd69\ucd6a\ucd6b\ucd6c\ucd6d\ucd6e\ucd6f\ucd70\ucd71\ucd72\ucd73\ucd74\ucd75\ucd76\ucd77\ucd78\ucd79\ucd7a\ucd7b\ucd7c\ucd7d\ucd7e\ucd7f\ucd80\ucd81\ucd82\ucd83\ucd84\ucd85\ucd86\ucd87\ucd88\ucd89\ucd8a\ucd8b\ucd8c\ucd8d\ucd8e\ucd8f\ucd90\ucd91\ucd92\ucd93\ucd94\ucd95\ucd96\ucd97\ucd98\ucd99\ucd9a\ucd9b\ucd9c\ucd9d\ucd9e\ucd9f\ucda0\ucda1\ucda2\ucda3\ucda4\ucda5\ucda6\ucda7\ucda8\ucda9\ucdaa\ucdab\ucdac\ucdad\ucdae\ucdaf\ucdb0\ucdb1\ucdb2\ucdb3\ucdb4\ucdb5\ucdb6\ucdb7\ucdb8\ucdb9\ucdba\ucdbb\ucdbc\ucdbd\ucdbe\ucdbf\ucdc0\ucdc1\ucdc2\ucdc3\ucdc4\ucdc5\ucdc6\ucdc7\ucdc8\ucdc9\ucdca\ucdcb\ucdcc\ucdcd\ucdce\ucdcf\ucdd0\ucdd1\ucdd2\ucdd3\ucdd4\ucdd5\ucdd6\ucdd7\ucdd8\ucdd9\ucdda\ucddb\ucddc\ucddd\ucdde\ucddf\ucde0\ucde1\ucde2\ucde3\ucde4\ucde5\ucde6\ucde7\ucde8\ucde9\ucdea\ucdeb\ucdec\ucded\ucdee\ucdef\ucdf0\ucdf1\ucdf2\ucdf3\ucdf4\ucdf5\ucdf6\ucdf7\ucdf8\ucdf9\ucdfa\ucdfb\ucdfc\ucdfd\ucdfe\ucdff\uce00\uce01\uce02\uce03\uce04\uce05\uce06\uce07\uce08\uce09\uce0a\uce0b\uce0c\uce0d\uce0e\uce0f\uce10\uce11\uce12\uce13\uce14\uce15\uce16\uce17\uce18\uce19\uce1a\uce1b\uce1c\uce1d\uce1e\uce1f\uce20\uce21\uce22\uce23\uce24\uce25\uce26\uce27\uce28\uce29\uce2a\uce2b\uce2c\uce2d\uce2e\uce2f\uce30\uce31\uce32\uce33\uce34\uce35\uce36\uce37\uce38\uce39\uce3a\uce3b\uce3c\uce3d\uce3e\uce3f\uce40\uce41\uce42\uce43\uce44\uce45\uce46\uce47\uce48\uce49\uce4a\uce4b\uce4c\uce4d\uce4e\uce4f\uce50\uce51\uce52\uce53\uce54\uce55\uce56\uce57\uce58\uce59\uce5a\uce5b\uce5c\uce5d\uce5e\uce5f\uce60\uce61\uce62\uce63\uce64\uce65\uce66\uce67\uce68\uce69\uce6a\uce6b\uce6c\uce6d\uce6e\uce6f\uce70\uce71\uce72\uce73\uce74\uce75\uce76\uce77\uce78\uce79\uce7a\uce7b\uce7c\uce7d\uce7e\uce7f\uce80\uce81\uce82\uce83\uce84\uce85\uce86\uce87\uce88\uce89\uce8a\uce8b\uce8c\uce8d\uce8e\uce8f\uce90\uce91\uce92\uce93\uce94\uce95\uce96\uce97\uce98\uce99\uce9a\uce9b\uce9c\uce9d\uce9e\uce9f\ucea0\ucea1\ucea2\ucea3\ucea4\ucea5\ucea6\ucea7\ucea8\ucea9\uceaa\uceab\uceac\ucead\uceae\uceaf\uceb0\uceb1\uceb2\uceb3\uceb4\uceb5\uceb6\uceb7\uceb8\uceb9\uceba\ucebb\ucebc\ucebd\ucebe\ucebf\ucec0\ucec1\ucec2\ucec3\ucec4\ucec5\ucec6\ucec7\ucec8\ucec9\uceca\ucecb\ucecc\ucecd\ucece\ucecf\uced0\uced1\uced2\uced3\uced4\uced5\uced6\uced7\uced8\uced9\uceda\ucedb\ucedc\ucedd\ucede\ucedf\ucee0\ucee1\ucee2\ucee3\ucee4\ucee5\ucee6\ucee7\ucee8\ucee9\uceea\uceeb\uceec\uceed\uceee\uceef\ucef0\ucef1\ucef2\ucef3\ucef4\ucef5\ucef6\ucef7\ucef8\ucef9\ucefa\ucefb\ucefc\ucefd\ucefe\uceff\ucf00\ucf01\ucf02\ucf03\ucf04\ucf05\ucf06\ucf07\ucf08\ucf09\ucf0a\ucf0b\ucf0c\ucf0d\ucf0e\ucf0f\ucf10\ucf11\ucf12\ucf13\ucf14\ucf15\ucf16\ucf17\ucf18\ucf19\ucf1a\ucf1b\ucf1c\ucf1d\ucf1e\ucf1f\ucf20\ucf21\ucf22\ucf23\ucf24\ucf25\ucf26\ucf27\ucf28\ucf29\ucf2a\ucf2b\ucf2c\ucf2d\ucf2e\ucf2f\ucf30\ucf31\ucf32\ucf33\ucf34\ucf35\ucf36\ucf37\ucf38\ucf39\ucf3a\ucf3b\ucf3c\ucf3d\ucf3e\ucf3f\ucf40\ucf41\ucf42\ucf43\ucf44\ucf45\ucf46\ucf47\ucf48\ucf49\ucf4a\ucf4b\ucf4c\ucf4d\ucf4e\ucf4f\ucf50\ucf51\ucf52\ucf53\ucf54\ucf55\ucf56\ucf57\ucf58\ucf59\ucf5a\ucf5b\ucf5c\ucf5d\ucf5e\ucf5f\ucf60\ucf61\ucf62\ucf63\ucf64\ucf65\ucf66\ucf67\ucf68\ucf69\ucf6a\ucf6b\ucf6c\ucf6d\ucf6e\ucf6f\ucf70\ucf71\ucf72\ucf73\ucf74\ucf75\ucf76\ucf77\ucf78\ucf79\ucf7a\ucf7b\ucf7c\ucf7d\ucf7e\ucf7f\ucf80\ucf81\ucf82\ucf83\ucf84\ucf85\ucf86\ucf87\ucf88\ucf89\ucf8a\ucf8b\ucf8c\ucf8d\ucf8e\ucf8f\ucf90\ucf91\ucf92\ucf93\ucf94\ucf95\ucf96\ucf97\ucf98\ucf99\ucf9a\ucf9b\ucf9c\ucf9d\ucf9e\ucf9f\ucfa0\ucfa1\ucfa2\ucfa3\ucfa4\ucfa5\ucfa6\ucfa7\ucfa8\ucfa9\ucfaa\ucfab\ucfac\ucfad\ucfae\ucfaf\ucfb0\ucfb1\ucfb2\ucfb3\ucfb4\ucfb5\ucfb6\ucfb7\ucfb8\ucfb9\ucfba\ucfbb\ucfbc\ucfbd\ucfbe\ucfbf\ucfc0\ucfc1\ucfc2\ucfc3\ucfc4\ucfc5\ucfc6\ucfc7\ucfc8\ucfc9\ucfca\ucfcb\ucfcc\ucfcd\ucfce\ucfcf\ucfd0\ucfd1\ucfd2\ucfd3\ucfd4\ucfd5\ucfd6\ucfd7\ucfd8\ucfd9\ucfda\ucfdb\ucfdc\ucfdd\ucfde\ucfdf\ucfe0\ucfe1\ucfe2\ucfe3\ucfe4\ucfe5\ucfe6\ucfe7\ucfe8\ucfe9\ucfea\ucfeb\ucfec\ucfed\ucfee\ucfef\ucff0\ucff1\ucff2\ucff3\ucff4\ucff5\ucff6\ucff7\ucff8\ucff9\ucffa\ucffb\ucffc\ucffd\ucffe\ucfff\ud000\ud001\ud002\ud003\ud004\ud005\ud006\ud007\ud008\ud009\ud00a\ud00b\ud00c\ud00d\ud00e\ud00f\ud010\ud011\ud012\ud013\ud014\ud015\ud016\ud017\ud018\ud019\ud01a\ud01b\ud01c\ud01d\ud01e\ud01f\ud020\ud021\ud022\ud023\ud024\ud025\ud026\ud027\ud028\ud029\ud02a\ud02b\ud02c\ud02d\ud02e\ud02f\ud030\ud031\ud032\ud033\ud034\ud035\ud036\ud037\ud038\ud039\ud03a\ud03b\ud03c\ud03d\ud03e\ud03f\ud040\ud041\ud042\ud043\ud044\ud045\ud046\ud047\ud048\ud049\ud04a\ud04b\ud04c\ud04d\ud04e\ud04f\ud050\ud051\ud052\ud053\ud054\ud055\ud056\ud057\ud058\ud059\ud05a\ud05b\ud05c\ud05d\ud05e\ud05f\ud060\ud061\ud062\ud063\ud064\ud065\ud066\ud067\ud068\ud069\ud06a\ud06b\ud06c\ud06d\ud06e\ud06f\ud070\ud071\ud072\ud073\ud074\ud075\ud076\ud077\ud078\ud079\ud07a\ud07b\ud07c\ud07d\ud07e\ud07f\ud080\ud081\ud082\ud083\ud084\ud085\ud086\ud087\ud088\ud089\ud08a\ud08b\ud08c\ud08d\ud08e\ud08f\ud090\ud091\ud092\ud093\ud094\ud095\ud096\ud097\ud098\ud099\ud09a\ud09b\ud09c\ud09d\ud09e\ud09f\ud0a0\ud0a1\ud0a2\ud0a3\ud0a4\ud0a5\ud0a6\ud0a7\ud0a8\ud0a9\ud0aa\ud0ab\ud0ac\ud0ad\ud0ae\ud0af\ud0b0\ud0b1\ud0b2\ud0b3\ud0b4\ud0b5\ud0b6\ud0b7\ud0b8\ud0b9\ud0ba\ud0bb\ud0bc\ud0bd\ud0be\ud0bf\ud0c0\ud0c1\ud0c2\ud0c3\ud0c4\ud0c5\ud0c6\ud0c7\ud0c8\ud0c9\ud0ca\ud0cb\ud0cc\ud0cd\ud0ce\ud0cf\ud0d0\ud0d1\ud0d2\ud0d3\ud0d4\ud0d5\ud0d6\ud0d7\ud0d8\ud0d9\ud0da\ud0db\ud0dc\ud0dd\ud0de\ud0df\ud0e0\ud0e1\ud0e2\ud0e3\ud0e4\ud0e5\ud0e6\ud0e7\ud0e8\ud0e9\ud0ea\ud0eb\ud0ec\ud0ed\ud0ee\ud0ef\ud0f0\ud0f1\ud0f2\ud0f3\ud0f4\ud0f5\ud0f6\ud0f7\ud0f8\ud0f9\ud0fa\ud0fb\ud0fc\ud0fd\ud0fe\ud0ff\ud100\ud101\ud102\ud103\ud104\ud105\ud106\ud107\ud108\ud109\ud10a\ud10b\ud10c\ud10d\ud10e\ud10f\ud110\ud111\ud112\ud113\ud114\ud115\ud116\ud117\ud118\ud119\ud11a\ud11b\ud11c\ud11d\ud11e\ud11f\ud120\ud121\ud122\ud123\ud124\ud125\ud126\ud127\ud128\ud129\ud12a\ud12b\ud12c\ud12d\ud12e\ud12f\ud130\ud131\ud132\ud133\ud134\ud135\ud136\ud137\ud138\ud139\ud13a\ud13b\ud13c\ud13d\ud13e\ud13f\ud140\ud141\ud142\ud143\ud144\ud145\ud146\ud147\ud148\ud149\ud14a\ud14b\ud14c\ud14d\ud14e\ud14f\ud150\ud151\ud152\ud153\ud154\ud155\ud156\ud157\ud158\ud159\ud15a\ud15b\ud15c\ud15d\ud15e\ud15f\ud160\ud161\ud162\ud163\ud164\ud165\ud166\ud167\ud168\ud169\ud16a\ud16b\ud16c\ud16d\ud16e\ud16f\ud170\ud171\ud172\ud173\ud174\ud175\ud176\ud177\ud178\ud179\ud17a\ud17b\ud17c\ud17d\ud17e\ud17f\ud180\ud181\ud182\ud183\ud184\ud185\ud186\ud187\ud188\ud189\ud18a\ud18b\ud18c\ud18d\ud18e\ud18f\ud190\ud191\ud192\ud193\ud194\ud195\ud196\ud197\ud198\ud199\ud19a\ud19b\ud19c\ud19d\ud19e\ud19f\ud1a0\ud1a1\ud1a2\ud1a3\ud1a4\ud1a5\ud1a6\ud1a7\ud1a8\ud1a9\ud1aa\ud1ab\ud1ac\ud1ad\ud1ae\ud1af\ud1b0\ud1b1\ud1b2\ud1b3\ud1b4\ud1b5\ud1b6\ud1b7\ud1b8\ud1b9\ud1ba\ud1bb\ud1bc\ud1bd\ud1be\ud1bf\ud1c0\ud1c1\ud1c2\ud1c3\ud1c4\ud1c5\ud1c6\ud1c7\ud1c8\ud1c9\ud1ca\ud1cb\ud1cc\ud1cd\ud1ce\ud1cf\ud1d0\ud1d1\ud1d2\ud1d3\ud1d4\ud1d5\ud1d6\ud1d7\ud1d8\ud1d9\ud1da\ud1db\ud1dc\ud1dd\ud1de\ud1df\ud1e0\ud1e1\ud1e2\ud1e3\ud1e4\ud1e5\ud1e6\ud1e7\ud1e8\ud1e9\ud1ea\ud1eb\ud1ec\ud1ed\ud1ee\ud1ef\ud1f0\ud1f1\ud1f2\ud1f3\ud1f4\ud1f5\ud1f6\ud1f7\ud1f8\ud1f9\ud1fa\ud1fb\ud1fc\ud1fd\ud1fe\ud1ff\ud200\ud201\ud202\ud203\ud204\ud205\ud206\ud207\ud208\ud209\ud20a\ud20b\ud20c\ud20d\ud20e\ud20f\ud210\ud211\ud212\ud213\ud214\ud215\ud216\ud217\ud218\ud219\ud21a\ud21b\ud21c\ud21d\ud21e\ud21f\ud220\ud221\ud222\ud223\ud224\ud225\ud226\ud227\ud228\ud229\ud22a\ud22b\ud22c\ud22d\ud22e\ud22f\ud230\ud231\ud232\ud233\ud234\ud235\ud236\ud237\ud238\ud239\ud23a\ud23b\ud23c\ud23d\ud23e\ud23f\ud240\ud241\ud242\ud243\ud244\ud245\ud246\ud247\ud248\ud249\ud24a\ud24b\ud24c\ud24d\ud24e\ud24f\ud250\ud251\ud252\ud253\ud254\ud255\ud256\ud257\ud258\ud259\ud25a\ud25b\ud25c\ud25d\ud25e\ud25f\ud260\ud261\ud262\ud263\ud264\ud265\ud266\ud267\ud268\ud269\ud26a\ud26b\ud26c\ud26d\ud26e\ud26f\ud270\ud271\ud272\ud273\ud274\ud275\ud276\ud277\ud278\ud279\ud27a\ud27b\ud27c\ud27d\ud27e\ud27f\ud280\ud281\ud282\ud283\ud284\ud285\ud286\ud287\ud288\ud289\ud28a\ud28b\ud28c\ud28d\ud28e\ud28f\ud290\ud291\ud292\ud293\ud294\ud295\ud296\ud297\ud298\ud299\ud29a\ud29b\ud29c\ud29d\ud29e\ud29f\ud2a0\ud2a1\ud2a2\ud2a3\ud2a4\ud2a5\ud2a6\ud2a7\ud2a8\ud2a9\ud2aa\ud2ab\ud2ac\ud2ad\ud2ae\ud2af\ud2b0\ud2b1\ud2b2\ud2b3\ud2b4\ud2b5\ud2b6\ud2b7\ud2b8\ud2b9\ud2ba\ud2bb\ud2bc\ud2bd\ud2be\ud2bf\ud2c0\ud2c1\ud2c2\ud2c3\ud2c4\ud2c5\ud2c6\ud2c7\ud2c8\ud2c9\ud2ca\ud2cb\ud2cc\ud2cd\ud2ce\ud2cf\ud2d0\ud2d1\ud2d2\ud2d3\ud2d4\ud2d5\ud2d6\ud2d7\ud2d8\ud2d9\ud2da\ud2db\ud2dc\ud2dd\ud2de\ud2df\ud2e0\ud2e1\ud2e2\ud2e3\ud2e4\ud2e5\ud2e6\ud2e7\ud2e8\ud2e9\ud2ea\ud2eb\ud2ec\ud2ed\ud2ee\ud2ef\ud2f0\ud2f1\ud2f2\ud2f3\ud2f4\ud2f5\ud2f6\ud2f7\ud2f8\ud2f9\ud2fa\ud2fb\ud2fc\ud2fd\ud2fe\ud2ff\ud300\ud301\ud302\ud303\ud304\ud305\ud306\ud307\ud308\ud309\ud30a\ud30b\ud30c\ud30d\ud30e\ud30f\ud310\ud311\ud312\ud313\ud314\ud315\ud316\ud317\ud318\ud319\ud31a\ud31b\ud31c\ud31d\ud31e\ud31f\ud320\ud321\ud322\ud323\ud324\ud325\ud326\ud327\ud328\ud329\ud32a\ud32b\ud32c\ud32d\ud32e\ud32f\ud330\ud331\ud332\ud333\ud334\ud335\ud336\ud337\ud338\ud339\ud33a\ud33b\ud33c\ud33d\ud33e\ud33f\ud340\ud341\ud342\ud343\ud344\ud345\ud346\ud347\ud348\ud349\ud34a\ud34b\ud34c\ud34d\ud34e\ud34f\ud350\ud351\ud352\ud353\ud354\ud355\ud356\ud357\ud358\ud359\ud35a\ud35b\ud35c\ud35d\ud35e\ud35f\ud360\ud361\ud362\ud363\ud364\ud365\ud366\ud367\ud368\ud369\ud36a\ud36b\ud36c\ud36d\ud36e\ud36f\ud370\ud371\ud372\ud373\ud374\ud375\ud376\ud377\ud378\ud379\ud37a\ud37b\ud37c\ud37d\ud37e\ud37f\ud380\ud381\ud382\ud383\ud384\ud385\ud386\ud387\ud388\ud389\ud38a\ud38b\ud38c\ud38d\ud38e\ud38f\ud390\ud391\ud392\ud393\ud394\ud395\ud396\ud397\ud398\ud399\ud39a\ud39b\ud39c\ud39d\ud39e\ud39f\ud3a0\ud3a1\ud3a2\ud3a3\ud3a4\ud3a5\ud3a6\ud3a7\ud3a8\ud3a9\ud3aa\ud3ab\ud3ac\ud3ad\ud3ae\ud3af\ud3b0\ud3b1\ud3b2\ud3b3\ud3b4\ud3b5\ud3b6\ud3b7\ud3b8\ud3b9\ud3ba\ud3bb\ud3bc\ud3bd\ud3be\ud3bf\ud3c0\ud3c1\ud3c2\ud3c3\ud3c4\ud3c5\ud3c6\ud3c7\ud3c8\ud3c9\ud3ca\ud3cb\ud3cc\ud3cd\ud3ce\ud3cf\ud3d0\ud3d1\ud3d2\ud3d3\ud3d4\ud3d5\ud3d6\ud3d7\ud3d8\ud3d9\ud3da\ud3db\ud3dc\ud3dd\ud3de\ud3df\ud3e0\ud3e1\ud3e2\ud3e3\ud3e4\ud3e5\ud3e6\ud3e7\ud3e8\ud3e9\ud3ea\ud3eb\ud3ec\ud3ed\ud3ee\ud3ef\ud3f0\ud3f1\ud3f2\ud3f3\ud3f4\ud3f5\ud3f6\ud3f7\ud3f8\ud3f9\ud3fa\ud3fb\ud3fc\ud3fd\ud3fe\ud3ff\ud400\ud401\ud402\ud403\ud404\ud405\ud406\ud407\ud408\ud409\ud40a\ud40b\ud40c\ud40d\ud40e\ud40f\ud410\ud411\ud412\ud413\ud414\ud415\ud416\ud417\ud418\ud419\ud41a\ud41b\ud41c\ud41d\ud41e\ud41f\ud420\ud421\ud422\ud423\ud424\ud425\ud426\ud427\ud428\ud429\ud42a\ud42b\ud42c\ud42d\ud42e\ud42f\ud430\ud431\ud432\ud433\ud434\ud435\ud436\ud437\ud438\ud439\ud43a\ud43b\ud43c\ud43d\ud43e\ud43f\ud440\ud441\ud442\ud443\ud444\ud445\ud446\ud447\ud448\ud449\ud44a\ud44b\ud44c\ud44d\ud44e\ud44f\ud450\ud451\ud452\ud453\ud454\ud455\ud456\ud457\ud458\ud459\ud45a\ud45b\ud45c\ud45d\ud45e\ud45f\ud460\ud461\ud462\ud463\ud464\ud465\ud466\ud467\ud468\ud469\ud46a\ud46b\ud46c\ud46d\ud46e\ud46f\ud470\ud471\ud472\ud473\ud474\ud475\ud476\ud477\ud478\ud479\ud47a\ud47b\ud47c\ud47d\ud47e\ud47f\ud480\ud481\ud482\ud483\ud484\ud485\ud486\ud487\ud488\ud489\ud48a\ud48b\ud48c\ud48d\ud48e\ud48f\ud490\ud491\ud492\ud493\ud494\ud495\ud496\ud497\ud498\ud499\ud49a\ud49b\ud49c\ud49d\ud49e\ud49f\ud4a0\ud4a1\ud4a2\ud4a3\ud4a4\ud4a5\ud4a6\ud4a7\ud4a8\ud4a9\ud4aa\ud4ab\ud4ac\ud4ad\ud4ae\ud4af\ud4b0\ud4b1\ud4b2\ud4b3\ud4b4\ud4b5\ud4b6\ud4b7\ud4b8\ud4b9\ud4ba\ud4bb\ud4bc\ud4bd\ud4be\ud4bf\ud4c0\ud4c1\ud4c2\ud4c3\ud4c4\ud4c5\ud4c6\ud4c7\ud4c8\ud4c9\ud4ca\ud4cb\ud4cc\ud4cd\ud4ce\ud4cf\ud4d0\ud4d1\ud4d2\ud4d3\ud4d4\ud4d5\ud4d6\ud4d7\ud4d8\ud4d9\ud4da\ud4db\ud4dc\ud4dd\ud4de\ud4df\ud4e0\ud4e1\ud4e2\ud4e3\ud4e4\ud4e5\ud4e6\ud4e7\ud4e8\ud4e9\ud4ea\ud4eb\ud4ec\ud4ed\ud4ee\ud4ef\ud4f0\ud4f1\ud4f2\ud4f3\ud4f4\ud4f5\ud4f6\ud4f7\ud4f8\ud4f9\ud4fa\ud4fb\ud4fc\ud4fd\ud4fe\ud4ff\ud500\ud501\ud502\ud503\ud504\ud505\ud506\ud507\ud508\ud509\ud50a\ud50b\ud50c\ud50d\ud50e\ud50f\ud510\ud511\ud512\ud513\ud514\ud515\ud516\ud517\ud518\ud519\ud51a\ud51b\ud51c\ud51d\ud51e\ud51f\ud520\ud521\ud522\ud523\ud524\ud525\ud526\ud527\ud528\ud529\ud52a\ud52b\ud52c\ud52d\ud52e\ud52f\ud530\ud531\ud532\ud533\ud534\ud535\ud536\ud537\ud538\ud539\ud53a\ud53b\ud53c\ud53d\ud53e\ud53f\ud540\ud541\ud542\ud543\ud544\ud545\ud546\ud547\ud548\ud549\ud54a\ud54b\ud54c\ud54d\ud54e\ud54f\ud550\ud551\ud552\ud553\ud554\ud555\ud556\ud557\ud558\ud559\ud55a\ud55b\ud55c\ud55d\ud55e\ud55f\ud560\ud561\ud562\ud563\ud564\ud565\ud566\ud567\ud568\ud569\ud56a\ud56b\ud56c\ud56d\ud56e\ud56f\ud570\ud571\ud572\ud573\ud574\ud575\ud576\ud577\ud578\ud579\ud57a\ud57b\ud57c\ud57d\ud57e\ud57f\ud580\ud581\ud582\ud583\ud584\ud585\ud586\ud587\ud588\ud589\ud58a\ud58b\ud58c\ud58d\ud58e\ud58f\ud590\ud591\ud592\ud593\ud594\ud595\ud596\ud597\ud598\ud599\ud59a\ud59b\ud59c\ud59d\ud59e\ud59f\ud5a0\ud5a1\ud5a2\ud5a3\ud5a4\ud5a5\ud5a6\ud5a7\ud5a8\ud5a9\ud5aa\ud5ab\ud5ac\ud5ad\ud5ae\ud5af\ud5b0\ud5b1\ud5b2\ud5b3\ud5b4\ud5b5\ud5b6\ud5b7\ud5b8\ud5b9\ud5ba\ud5bb\ud5bc\ud5bd\ud5be\ud5bf\ud5c0\ud5c1\ud5c2\ud5c3\ud5c4\ud5c5\ud5c6\ud5c7\ud5c8\ud5c9\ud5ca\ud5cb\ud5cc\ud5cd\ud5ce\ud5cf\ud5d0\ud5d1\ud5d2\ud5d3\ud5d4\ud5d5\ud5d6\ud5d7\ud5d8\ud5d9\ud5da\ud5db\ud5dc\ud5dd\ud5de\ud5df\ud5e0\ud5e1\ud5e2\ud5e3\ud5e4\ud5e5\ud5e6\ud5e7\ud5e8\ud5e9\ud5ea\ud5eb\ud5ec\ud5ed\ud5ee\ud5ef\ud5f0\ud5f1\ud5f2\ud5f3\ud5f4\ud5f5\ud5f6\ud5f7\ud5f8\ud5f9\ud5fa\ud5fb\ud5fc\ud5fd\ud5fe\ud5ff\ud600\ud601\ud602\ud603\ud604\ud605\ud606\ud607\ud608\ud609\ud60a\ud60b\ud60c\ud60d\ud60e\ud60f\ud610\ud611\ud612\ud613\ud614\ud615\ud616\ud617\ud618\ud619\ud61a\ud61b\ud61c\ud61d\ud61e\ud61f\ud620\ud621\ud622\ud623\ud624\ud625\ud626\ud627\ud628\ud629\ud62a\ud62b\ud62c\ud62d\ud62e\ud62f\ud630\ud631\ud632\ud633\ud634\ud635\ud636\ud637\ud638\ud639\ud63a\ud63b\ud63c\ud63d\ud63e\ud63f\ud640\ud641\ud642\ud643\ud644\ud645\ud646\ud647\ud648\ud649\ud64a\ud64b\ud64c\ud64d\ud64e\ud64f\ud650\ud651\ud652\ud653\ud654\ud655\ud656\ud657\ud658\ud659\ud65a\ud65b\ud65c\ud65d\ud65e\ud65f\ud660\ud661\ud662\ud663\ud664\ud665\ud666\ud667\ud668\ud669\ud66a\ud66b\ud66c\ud66d\ud66e\ud66f\ud670\ud671\ud672\ud673\ud674\ud675\ud676\ud677\ud678\ud679\ud67a\ud67b\ud67c\ud67d\ud67e\ud67f\ud680\ud681\ud682\ud683\ud684\ud685\ud686\ud687\ud688\ud689\ud68a\ud68b\ud68c\ud68d\ud68e\ud68f\ud690\ud691\ud692\ud693\ud694\ud695\ud696\ud697\ud698\ud699\ud69a\ud69b\ud69c\ud69d\ud69e\ud69f\ud6a0\ud6a1\ud6a2\ud6a3\ud6a4\ud6a5\ud6a6\ud6a7\ud6a8\ud6a9\ud6aa\ud6ab\ud6ac\ud6ad\ud6ae\ud6af\ud6b0\ud6b1\ud6b2\ud6b3\ud6b4\ud6b5\ud6b6\ud6b7\ud6b8\ud6b9\ud6ba\ud6bb\ud6bc\ud6bd\ud6be\ud6bf\ud6c0\ud6c1\ud6c2\ud6c3\ud6c4\ud6c5\ud6c6\ud6c7\ud6c8\ud6c9\ud6ca\ud6cb\ud6cc\ud6cd\ud6ce\ud6cf\ud6d0\ud6d1\ud6d2\ud6d3\ud6d4\ud6d5\ud6d6\ud6d7\ud6d8\ud6d9\ud6da\ud6db\ud6dc\ud6dd\ud6de\ud6df\ud6e0\ud6e1\ud6e2\ud6e3\ud6e4\ud6e5\ud6e6\ud6e7\ud6e8\ud6e9\ud6ea\ud6eb\ud6ec\ud6ed\ud6ee\ud6ef\ud6f0\ud6f1\ud6f2\ud6f3\ud6f4\ud6f5\ud6f6\ud6f7\ud6f8\ud6f9\ud6fa\ud6fb\ud6fc\ud6fd\ud6fe\ud6ff\ud700\ud701\ud702\ud703\ud704\ud705\ud706\ud707\ud708\ud709\ud70a\ud70b\ud70c\ud70d\ud70e\ud70f\ud710\ud711\ud712\ud713\ud714\ud715\ud716\ud717\ud718\ud719\ud71a\ud71b\ud71c\ud71d\ud71e\ud71f\ud720\ud721\ud722\ud723\ud724\ud725\ud726\ud727\ud728\ud729\ud72a\ud72b\ud72c\ud72d\ud72e\ud72f\ud730\ud731\ud732\ud733\ud734\ud735\ud736\ud737\ud738\ud739\ud73a\ud73b\ud73c\ud73d\ud73e\ud73f\ud740\ud741\ud742\ud743\ud744\ud745\ud746\ud747\ud748\ud749\ud74a\ud74b\ud74c\ud74d\ud74e\ud74f\ud750\ud751\ud752\ud753\ud754\ud755\ud756\ud757\ud758\ud759\ud75a\ud75b\ud75c\ud75d\ud75e\ud75f\ud760\ud761\ud762\ud763\ud764\ud765\ud766\ud767\ud768\ud769\ud76a\ud76b\ud76c\ud76d\ud76e\ud76f\ud770\ud771\ud772\ud773\ud774\ud775\ud776\ud777\ud778\ud779\ud77a\ud77b\ud77c\ud77d\ud77e\ud77f\ud780\ud781\ud782\ud783\ud784\ud785\ud786\ud787\ud788\ud789\ud78a\ud78b\ud78c\ud78d\ud78e\ud78f\ud790\ud791\ud792\ud793\ud794\ud795\ud796\ud797\ud798\ud799\ud79a\ud79b\ud79c\ud79d\ud79e\ud79f\ud7a0\ud7a1\ud7a2\ud7a3\uf900\uf901\uf902\uf903\uf904\uf905\uf906\uf907\uf908\uf909\uf90a\uf90b\uf90c\uf90d\uf90e\uf90f\uf910\uf911\uf912\uf913\uf914\uf915\uf916\uf917\uf918\uf919\uf91a\uf91b\uf91c\uf91d\uf91e\uf91f\uf920\uf921\uf922\uf923\uf924\uf925\uf926\uf927\uf928\uf929\uf92a\uf92b\uf92c\uf92d\uf92e\uf92f\uf930\uf931\uf932\uf933\uf934\uf935\uf936\uf937\uf938\uf939\uf93a\uf93b\uf93c\uf93d\uf93e\uf93f\uf940\uf941\uf942\uf943\uf944\uf945\uf946\uf947\uf948\uf949\uf94a\uf94b\uf94c\uf94d\uf94e\uf94f\uf950\uf951\uf952\uf953\uf954\uf955\uf956\uf957\uf958\uf959\uf95a\uf95b\uf95c\uf95d\uf95e\uf95f\uf960\uf961\uf962\uf963\uf964\uf965\uf966\uf967\uf968\uf969\uf96a\uf96b\uf96c\uf96d\uf96e\uf96f\uf970\uf971\uf972\uf973\uf974\uf975\uf976\uf977\uf978\uf979\uf97a\uf97b\uf97c\uf97d\uf97e\uf97f\uf980\uf981\uf982\uf983\uf984\uf985\uf986\uf987\uf988\uf989\uf98a\uf98b\uf98c\uf98d\uf98e\uf98f\uf990\uf991\uf992\uf993\uf994\uf995\uf996\uf997\uf998\uf999\uf99a\uf99b\uf99c\uf99d\uf99e\uf99f\uf9a0\uf9a1\uf9a2\uf9a3\uf9a4\uf9a5\uf9a6\uf9a7\uf9a8\uf9a9\uf9aa\uf9ab\uf9ac\uf9ad\uf9ae\uf9af\uf9b0\uf9b1\uf9b2\uf9b3\uf9b4\uf9b5\uf9b6\uf9b7\uf9b8\uf9b9\uf9ba\uf9bb\uf9bc\uf9bd\uf9be\uf9bf\uf9c0\uf9c1\uf9c2\uf9c3\uf9c4\uf9c5\uf9c6\uf9c7\uf9c8\uf9c9\uf9ca\uf9cb\uf9cc\uf9cd\uf9ce\uf9cf\uf9d0\uf9d1\uf9d2\uf9d3\uf9d4\uf9d5\uf9d6\uf9d7\uf9d8\uf9d9\uf9da\uf9db\uf9dc\uf9dd\uf9de\uf9df\uf9e0\uf9e1\uf9e2\uf9e3\uf9e4\uf9e5\uf9e6\uf9e7\uf9e8\uf9e9\uf9ea\uf9eb\uf9ec\uf9ed\uf9ee\uf9ef\uf9f0\uf9f1\uf9f2\uf9f3\uf9f4\uf9f5\uf9f6\uf9f7\uf9f8\uf9f9\uf9fa\uf9fb\uf9fc\uf9fd\uf9fe\uf9ff\ufa00\ufa01\ufa02\ufa03\ufa04\ufa05\ufa06\ufa07\ufa08\ufa09\ufa0a\ufa0b\ufa0c\ufa0d\ufa0e\ufa0f\ufa10\ufa11\ufa12\ufa13\ufa14\ufa15\ufa16\ufa17\ufa18\ufa19\ufa1a\ufa1b\ufa1c\ufa1d\ufa1e\ufa1f\ufa20\ufa21\ufa22\ufa23\ufa24\ufa25\ufa26\ufa27\ufa28\ufa29\ufa2a\ufa2b\ufa2c\ufa2d\ufa30\ufa31\ufa32\ufa33\ufa34\ufa35\ufa36\ufa37\ufa38\ufa39\ufa3a\ufa3b\ufa3c\ufa3d\ufa3e\ufa3f\ufa40\ufa41\ufa42\ufa43\ufa44\ufa45\ufa46\ufa47\ufa48\ufa49\ufa4a\ufa4b\ufa4c\ufa4d\ufa4e\ufa4f\ufa50\ufa51\ufa52\ufa53\ufa54\ufa55\ufa56\ufa57\ufa58\ufa59\ufa5a\ufa5b\ufa5c\ufa5d\ufa5e\ufa5f\ufa60\ufa61\ufa62\ufa63\ufa64\ufa65\ufa66\ufa67\ufa68\ufa69\ufa6a\ufa70\ufa71\ufa72\ufa73\ufa74\ufa75\ufa76\ufa77\ufa78\ufa79\ufa7a\ufa7b\ufa7c\ufa7d\ufa7e\ufa7f\ufa80\ufa81\ufa82\ufa83\ufa84\ufa85\ufa86\ufa87\ufa88\ufa89\ufa8a\ufa8b\ufa8c\ufa8d\ufa8e\ufa8f\ufa90\ufa91\ufa92\ufa93\ufa94\ufa95\ufa96\ufa97\ufa98\ufa99\ufa9a\ufa9b\ufa9c\ufa9d\ufa9e\ufa9f\ufaa0\ufaa1\ufaa2\ufaa3\ufaa4\ufaa5\ufaa6\ufaa7\ufaa8\ufaa9\ufaaa\ufaab\ufaac\ufaad\ufaae\ufaaf\ufab0\ufab1\ufab2\ufab3\ufab4\ufab5\ufab6\ufab7\ufab8\ufab9\ufaba\ufabb\ufabc\ufabd\ufabe\ufabf\ufac0\ufac1\ufac2\ufac3\ufac4\ufac5\ufac6\ufac7\ufac8\ufac9\ufaca\ufacb\ufacc\ufacd\uface\ufacf\ufad0\ufad1\ufad2\ufad3\ufad4\ufad5\ufad6\ufad7\ufad8\ufad9\ufb1d\ufb1f\ufb20\ufb21\ufb22\ufb23\ufb24\ufb25\ufb26\ufb27\ufb28\ufb2a\ufb2b\ufb2c\ufb2d\ufb2e\ufb2f\ufb30\ufb31\ufb32\ufb33\ufb34\ufb35\ufb36\ufb38\ufb39\ufb3a\ufb3b\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46\ufb47\ufb48\ufb49\ufb4a\ufb4b\ufb4c\ufb4d\ufb4e\ufb4f\ufb50\ufb51\ufb52\ufb53\ufb54\ufb55\ufb56\ufb57\ufb58\ufb59\ufb5a\ufb5b\ufb5c\ufb5d\ufb5e\ufb5f\ufb60\ufb61\ufb62\ufb63\ufb64\ufb65\ufb66\ufb67\ufb68\ufb69\ufb6a\ufb6b\ufb6c\ufb6d\ufb6e\ufb6f\ufb70\ufb71\ufb72\ufb73\ufb74\ufb75\ufb76\ufb77\ufb78\ufb79\ufb7a\ufb7b\ufb7c\ufb7d\ufb7e\ufb7f\ufb80\ufb81\ufb82\ufb83\ufb84\ufb85\ufb86\ufb87\ufb88\ufb89\ufb8a\ufb8b\ufb8c\ufb8d\ufb8e\ufb8f\ufb90\ufb91\ufb92\ufb93\ufb94\ufb95\ufb96\ufb97\ufb98\ufb99\ufb9a\ufb9b\ufb9c\ufb9d\ufb9e\ufb9f\ufba0\ufba1\ufba2\ufba3\ufba4\ufba5\ufba6\ufba7\ufba8\ufba9\ufbaa\ufbab\ufbac\ufbad\ufbae\ufbaf\ufbb0\ufbb1\ufbd3\ufbd4\ufbd5\ufbd6\ufbd7\ufbd8\ufbd9\ufbda\ufbdb\ufbdc\ufbdd\ufbde\ufbdf\ufbe0\ufbe1\ufbe2\ufbe3\ufbe4\ufbe5\ufbe6\ufbe7\ufbe8\ufbe9\ufbea\ufbeb\ufbec\ufbed\ufbee\ufbef\ufbf0\ufbf1\ufbf2\ufbf3\ufbf4\ufbf5\ufbf6\ufbf7\ufbf8\ufbf9\ufbfa\ufbfb\ufbfc\ufbfd\ufbfe\ufbff\ufc00\ufc01\ufc02\ufc03\ufc04\ufc05\ufc06\ufc07\ufc08\ufc09\ufc0a\ufc0b\ufc0c\ufc0d\ufc0e\ufc0f\ufc10\ufc11\ufc12\ufc13\ufc14\ufc15\ufc16\ufc17\ufc18\ufc19\ufc1a\ufc1b\ufc1c\ufc1d\ufc1e\ufc1f\ufc20\ufc21\ufc22\ufc23\ufc24\ufc25\ufc26\ufc27\ufc28\ufc29\ufc2a\ufc2b\ufc2c\ufc2d\ufc2e\ufc2f\ufc30\ufc31\ufc32\ufc33\ufc34\ufc35\ufc36\ufc37\ufc38\ufc39\ufc3a\ufc3b\ufc3c\ufc3d\ufc3e\ufc3f\ufc40\ufc41\ufc42\ufc43\ufc44\ufc45\ufc46\ufc47\ufc48\ufc49\ufc4a\ufc4b\ufc4c\ufc4d\ufc4e\ufc4f\ufc50\ufc51\ufc52\ufc53\ufc54\ufc55\ufc56\ufc57\ufc58\ufc59\ufc5a\ufc5b\ufc5c\ufc5d\ufc5e\ufc5f\ufc60\ufc61\ufc62\ufc63\ufc64\ufc65\ufc66\ufc67\ufc68\ufc69\ufc6a\ufc6b\ufc6c\ufc6d\ufc6e\ufc6f\ufc70\ufc71\ufc72\ufc73\ufc74\ufc75\ufc76\ufc77\ufc78\ufc79\ufc7a\ufc7b\ufc7c\ufc7d\ufc7e\ufc7f\ufc80\ufc81\ufc82\ufc83\ufc84\ufc85\ufc86\ufc87\ufc88\ufc89\ufc8a\ufc8b\ufc8c\ufc8d\ufc8e\ufc8f\ufc90\ufc91\ufc92\ufc93\ufc94\ufc95\ufc96\ufc97\ufc98\ufc99\ufc9a\ufc9b\ufc9c\ufc9d\ufc9e\ufc9f\ufca0\ufca1\ufca2\ufca3\ufca4\ufca5\ufca6\ufca7\ufca8\ufca9\ufcaa\ufcab\ufcac\ufcad\ufcae\ufcaf\ufcb0\ufcb1\ufcb2\ufcb3\ufcb4\ufcb5\ufcb6\ufcb7\ufcb8\ufcb9\ufcba\ufcbb\ufcbc\ufcbd\ufcbe\ufcbf\ufcc0\ufcc1\ufcc2\ufcc3\ufcc4\ufcc5\ufcc6\ufcc7\ufcc8\ufcc9\ufcca\ufccb\ufccc\ufccd\ufcce\ufccf\ufcd0\ufcd1\ufcd2\ufcd3\ufcd4\ufcd5\ufcd6\ufcd7\ufcd8\ufcd9\ufcda\ufcdb\ufcdc\ufcdd\ufcde\ufcdf\ufce0\ufce1\ufce2\ufce3\ufce4\ufce5\ufce6\ufce7\ufce8\ufce9\ufcea\ufceb\ufcec\ufced\ufcee\ufcef\ufcf0\ufcf1\ufcf2\ufcf3\ufcf4\ufcf5\ufcf6\ufcf7\ufcf8\ufcf9\ufcfa\ufcfb\ufcfc\ufcfd\ufcfe\ufcff\ufd00\ufd01\ufd02\ufd03\ufd04\ufd05\ufd06\ufd07\ufd08\ufd09\ufd0a\ufd0b\ufd0c\ufd0d\ufd0e\ufd0f\ufd10\ufd11\ufd12\ufd13\ufd14\ufd15\ufd16\ufd17\ufd18\ufd19\ufd1a\ufd1b\ufd1c\ufd1d\ufd1e\ufd1f\ufd20\ufd21\ufd22\ufd23\ufd24\ufd25\ufd26\ufd27\ufd28\ufd29\ufd2a\ufd2b\ufd2c\ufd2d\ufd2e\ufd2f\ufd30\ufd31\ufd32\ufd33\ufd34\ufd35\ufd36\ufd37\ufd38\ufd39\ufd3a\ufd3b\ufd3c\ufd3d\ufd50\ufd51\ufd52\ufd53\ufd54\ufd55\ufd56\ufd57\ufd58\ufd59\ufd5a\ufd5b\ufd5c\ufd5d\ufd5e\ufd5f\ufd60\ufd61\ufd62\ufd63\ufd64\ufd65\ufd66\ufd67\ufd68\ufd69\ufd6a\ufd6b\ufd6c\ufd6d\ufd6e\ufd6f\ufd70\ufd71\ufd72\ufd73\ufd74\ufd75\ufd76\ufd77\ufd78\ufd79\ufd7a\ufd7b\ufd7c\ufd7d\ufd7e\ufd7f\ufd80\ufd81\ufd82\ufd83\ufd84\ufd85\ufd86\ufd87\ufd88\ufd89\ufd8a\ufd8b\ufd8c\ufd8d\ufd8e\ufd8f\ufd92\ufd93\ufd94\ufd95\ufd96\ufd97\ufd98\ufd99\ufd9a\ufd9b\ufd9c\ufd9d\ufd9e\ufd9f\ufda0\ufda1\ufda2\ufda3\ufda4\ufda5\ufda6\ufda7\ufda8\ufda9\ufdaa\ufdab\ufdac\ufdad\ufdae\ufdaf\ufdb0\ufdb1\ufdb2\ufdb3\ufdb4\ufdb5\ufdb6\ufdb7\ufdb8\ufdb9\ufdba\ufdbb\ufdbc\ufdbd\ufdbe\ufdbf\ufdc0\ufdc1\ufdc2\ufdc3\ufdc4\ufdc5\ufdc6\ufdc7\ufdf0\ufdf1\ufdf2\ufdf3\ufdf4\ufdf5\ufdf6\ufdf7\ufdf8\ufdf9\ufdfa\ufdfb\ufe70\ufe71\ufe72\ufe73\ufe74\ufe76\ufe77\ufe78\ufe79\ufe7a\ufe7b\ufe7c\ufe7d\ufe7e\ufe7f\ufe80\ufe81\ufe82\ufe83\ufe84\ufe85\ufe86\ufe87\ufe88\ufe89\ufe8a\ufe8b\ufe8c\ufe8d\ufe8e\ufe8f\ufe90\ufe91\ufe92\ufe93\ufe94\ufe95\ufe96\ufe97\ufe98\ufe99\ufe9a\ufe9b\ufe9c\ufe9d\ufe9e\ufe9f\ufea0\ufea1\ufea2\ufea3\ufea4\ufea5\ufea6\ufea7\ufea8\ufea9\ufeaa\ufeab\ufeac\ufead\ufeae\ufeaf\ufeb0\ufeb1\ufeb2\ufeb3\ufeb4\ufeb5\ufeb6\ufeb7\ufeb8\ufeb9\ufeba\ufebb\ufebc\ufebd\ufebe\ufebf\ufec0\ufec1\ufec2\ufec3\ufec4\ufec5\ufec6\ufec7\ufec8\ufec9\ufeca\ufecb\ufecc\ufecd\ufece\ufecf\ufed0\ufed1\ufed2\ufed3\ufed4\ufed5\ufed6\ufed7\ufed8\ufed9\ufeda\ufedb\ufedc\ufedd\ufede\ufedf\ufee0\ufee1\ufee2\ufee3\ufee4\ufee5\ufee6\ufee7\ufee8\ufee9\ufeea\ufeeb\ufeec\ufeed\ufeee\ufeef\ufef0\ufef1\ufef2\ufef3\ufef4\ufef5\ufef6\ufef7\ufef8\ufef9\ufefa\ufefb\ufefc\uff66\uff67\uff68\uff69\uff6a\uff6b\uff6c\uff6d\uff6e\uff6f\uff71\uff72\uff73\uff74\uff75\uff76\uff77\uff78\uff79\uff7a\uff7b\uff7c\uff7d\uff7e\uff7f\uff80\uff81\uff82\uff83\uff84\uff85\uff86\uff87\uff88\uff89\uff8a\uff8b\uff8c\uff8d\uff8e\uff8f\uff90\uff91\uff92\uff93\uff94\uff95\uff96\uff97\uff98\uff99\uff9a\uff9b\uff9c\uff9d\uffa0\uffa1\uffa2\uffa3\uffa4\uffa5\uffa6\uffa7\uffa8\uffa9\uffaa\uffab\uffac\uffad\uffae\uffaf\uffb0\uffb1\uffb2\uffb3\uffb4\uffb5\uffb6\uffb7\uffb8\uffb9\uffba\uffbb\uffbc\uffbd\uffbe\uffc2\uffc3\uffc4\uffc5\uffc6\uffc7\uffca\uffcb\uffcc\uffcd\uffce\uffcf\uffd2\uffd3\uffd4\uffd5\uffd6\uffd7\uffda\uffdb\uffdc'
+
+Lt = u'\u01c5\u01c8\u01cb\u01f2\u1f88\u1f89\u1f8a\u1f8b\u1f8c\u1f8d\u1f8e\u1f8f\u1f98\u1f99\u1f9a\u1f9b\u1f9c\u1f9d\u1f9e\u1f9f\u1fa8\u1fa9\u1faa\u1fab\u1fac\u1fad\u1fae\u1faf\u1fbc\u1fcc\u1ffc'
+
+Lu = u'ABCDEFGHIJKLMNOPQRSTUVWXYZ\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd8\xd9\xda\xdb\xdc\xdd\xde\u0100\u0102\u0104\u0106\u0108\u010a\u010c\u010e\u0110\u0112\u0114\u0116\u0118\u011a\u011c\u011e\u0120\u0122\u0124\u0126\u0128\u012a\u012c\u012e\u0130\u0132\u0134\u0136\u0139\u013b\u013d\u013f\u0141\u0143\u0145\u0147\u014a\u014c\u014e\u0150\u0152\u0154\u0156\u0158\u015a\u015c\u015e\u0160\u0162\u0164\u0166\u0168\u016a\u016c\u016e\u0170\u0172\u0174\u0176\u0178\u0179\u017b\u017d\u0181\u0182\u0184\u0186\u0187\u0189\u018a\u018b\u018e\u018f\u0190\u0191\u0193\u0194\u0196\u0197\u0198\u019c\u019d\u019f\u01a0\u01a2\u01a4\u01a6\u01a7\u01a9\u01ac\u01ae\u01af\u01b1\u01b2\u01b3\u01b5\u01b7\u01b8\u01bc\u01c4\u01c7\u01ca\u01cd\u01cf\u01d1\u01d3\u01d5\u01d7\u01d9\u01db\u01de\u01e0\u01e2\u01e4\u01e6\u01e8\u01ea\u01ec\u01ee\u01f1\u01f4\u01f6\u01f7\u01f8\u01fa\u01fc\u01fe\u0200\u0202\u0204\u0206\u0208\u020a\u020c\u020e\u0210\u0212\u0214\u0216\u0218\u021a\u021c\u021e\u0220\u0222\u0224\u0226\u0228\u022a\u022c\u022e\u0230\u0232\u023a\u023b\u023d\u023e\u0241\u0386\u0388\u0389\u038a\u038c\u038e\u038f\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039a\u039b\u039c\u039d\u039e\u039f\u03a0\u03a1\u03a3\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9\u03aa\u03ab\u03d2\u03d3\u03d4\u03d8\u03da\u03dc\u03de\u03e0\u03e2\u03e4\u03e6\u03e8\u03ea\u03ec\u03ee\u03f4\u03f7\u03f9\u03fa\u03fd\u03fe\u03ff\u0400\u0401\u0402\u0403\u0404\u0405\u0406\u0407\u0408\u0409\u040a\u040b\u040c\u040d\u040e\u040f\u0410\u0411\u0412\u0413\u0414\u0415\u0416\u0417\u0418\u0419\u041a\u041b\u041c\u041d\u041e\u041f\u0420\u0421\u0422\u0423\u0424\u0425\u0426\u0427\u0428\u0429\u042a\u042b\u042c\u042d\u042e\u042f\u0460\u0462\u0464\u0466\u0468\u046a\u046c\u046e\u0470\u0472\u0474\u0476\u0478\u047a\u047c\u047e\u0480\u048a\u048c\u048e\u0490\u0492\u0494\u0496\u0498\u049a\u049c\u049e\u04a0\u04a2\u04a4\u04a6\u04a8\u04aa\u04ac\u04ae\u04b0\u04b2\u04b4\u04b6\u04b8\u04ba\u04bc\u04be\u04c0\u04c1\u04c3\u04c5\u04c7\u04c9\u04cb\u04cd\u04d0\u04d2\u04d4\u04d6\u04d8\u04da\u04dc\u04de\u04e0\u04e2\u04e4\u04e6\u04e8\u04ea\u04ec\u04ee\u04f0\u04f2\u04f4\u04f6\u04f8\u0500\u0502\u0504\u0506\u0508\u050a\u050c\u050e\u0531\u0532\u0533\u0534\u0535\u0536\u0537\u0538\u0539\u053a\u053b\u053c\u053d\u053e\u053f\u0540\u0541\u0542\u0543\u0544\u0545\u0546\u0547\u0548\u0549\u054a\u054b\u054c\u054d\u054e\u054f\u0550\u0551\u0552\u0553\u0554\u0555\u0556\u10a0\u10a1\u10a2\u10a3\u10a4\u10a5\u10a6\u10a7\u10a8\u10a9\u10aa\u10ab\u10ac\u10ad\u10ae\u10af\u10b0\u10b1\u10b2\u10b3\u10b4\u10b5\u10b6\u10b7\u10b8\u10b9\u10ba\u10bb\u10bc\u10bd\u10be\u10bf\u10c0\u10c1\u10c2\u10c3\u10c4\u10c5\u1e00\u1e02\u1e04\u1e06\u1e08\u1e0a\u1e0c\u1e0e\u1e10\u1e12\u1e14\u1e16\u1e18\u1e1a\u1e1c\u1e1e\u1e20\u1e22\u1e24\u1e26\u1e28\u1e2a\u1e2c\u1e2e\u1e30\u1e32\u1e34\u1e36\u1e38\u1e3a\u1e3c\u1e3e\u1e40\u1e42\u1e44\u1e46\u1e48\u1e4a\u1e4c\u1e4e\u1e50\u1e52\u1e54\u1e56\u1e58\u1e5a\u1e5c\u1e5e\u1e60\u1e62\u1e64\u1e66\u1e68\u1e6a\u1e6c\u1e6e\u1e70\u1e72\u1e74\u1e76\u1e78\u1e7a\u1e7c\u1e7e\u1e80\u1e82\u1e84\u1e86\u1e88\u1e8a\u1e8c\u1e8e\u1e90\u1e92\u1e94\u1ea0\u1ea2\u1ea4\u1ea6\u1ea8\u1eaa\u1eac\u1eae\u1eb0\u1eb2\u1eb4\u1eb6\u1eb8\u1eba\u1ebc\u1ebe\u1ec0\u1ec2\u1ec4\u1ec6\u1ec8\u1eca\u1ecc\u1ece\u1ed0\u1ed2\u1ed4\u1ed6\u1ed8\u1eda\u1edc\u1ede\u1ee0\u1ee2\u1ee4\u1ee6\u1ee8\u1eea\u1eec\u1eee\u1ef0\u1ef2\u1ef4\u1ef6\u1ef8\u1f08\u1f09\u1f0a\u1f0b\u1f0c\u1f0d\u1f0e\u1f0f\u1f18\u1f19\u1f1a\u1f1b\u1f1c\u1f1d\u1f28\u1f29\u1f2a\u1f2b\u1f2c\u1f2d\u1f2e\u1f2f\u1f38\u1f39\u1f3a\u1f3b\u1f3c\u1f3d\u1f3e\u1f3f\u1f48\u1f49\u1f4a\u1f4b\u1f4c\u1f4d\u1f59\u1f5b\u1f5d\u1f5f\u1f68\u1f69\u1f6a\u1f6b\u1f6c\u1f6d\u1f6e\u1f6f\u1fb8\u1fb9\u1fba\u1fbb\u1fc8\u1fc9\u1fca\u1fcb\u1fd8\u1fd9\u1fda\u1fdb\u1fe8\u1fe9\u1fea\u1feb\u1fec\u1ff8\u1ff9\u1ffa\u1ffb\u2102\u2107\u210b\u210c\u210d\u2110\u2111\u2112\u2115\u2119\u211a\u211b\u211c\u211d\u2124\u2126\u2128\u212a\u212b\u212c\u212d\u2130\u2131\u2133\u213e\u213f\u2145\u2c00\u2c01\u2c02\u2c03\u2c04\u2c05\u2c06\u2c07\u2c08\u2c09\u2c0a\u2c0b\u2c0c\u2c0d\u2c0e\u2c0f\u2c10\u2c11\u2c12\u2c13\u2c14\u2c15\u2c16\u2c17\u2c18\u2c19\u2c1a\u2c1b\u2c1c\u2c1d\u2c1e\u2c1f\u2c20\u2c21\u2c22\u2c23\u2c24\u2c25\u2c26\u2c27\u2c28\u2c29\u2c2a\u2c2b\u2c2c\u2c2d\u2c2e\u2c80\u2c82\u2c84\u2c86\u2c88\u2c8a\u2c8c\u2c8e\u2c90\u2c92\u2c94\u2c96\u2c98\u2c9a\u2c9c\u2c9e\u2ca0\u2ca2\u2ca4\u2ca6\u2ca8\u2caa\u2cac\u2cae\u2cb0\u2cb2\u2cb4\u2cb6\u2cb8\u2cba\u2cbc\u2cbe\u2cc0\u2cc2\u2cc4\u2cc6\u2cc8\u2cca\u2ccc\u2cce\u2cd0\u2cd2\u2cd4\u2cd6\u2cd8\u2cda\u2cdc\u2cde\u2ce0\u2ce2\uff21\uff22\uff23\uff24\uff25\uff26\uff27\uff28\uff29\uff2a\uff2b\uff2c\uff2d\uff2e\uff2f\uff30\uff31\uff32\uff33\uff34\uff35\uff36\uff37\uff38\uff39\uff3a'
+
+Mc = u'\u0903\u093e\u093f\u0940\u0949\u094a\u094b\u094c\u0982\u0983\u09be\u09bf\u09c0\u09c7\u09c8\u09cb\u09cc\u09d7\u0a03\u0a3e\u0a3f\u0a40\u0a83\u0abe\u0abf\u0ac0\u0ac9\u0acb\u0acc\u0b02\u0b03\u0b3e\u0b40\u0b47\u0b48\u0b4b\u0b4c\u0b57\u0bbe\u0bbf\u0bc1\u0bc2\u0bc6\u0bc7\u0bc8\u0bca\u0bcb\u0bcc\u0bd7\u0c01\u0c02\u0c03\u0c41\u0c42\u0c43\u0c44\u0c82\u0c83\u0cbe\u0cc0\u0cc1\u0cc2\u0cc3\u0cc4\u0cc7\u0cc8\u0cca\u0ccb\u0cd5\u0cd6\u0d02\u0d03\u0d3e\u0d3f\u0d40\u0d46\u0d47\u0d48\u0d4a\u0d4b\u0d4c\u0d57\u0d82\u0d83\u0dcf\u0dd0\u0dd1\u0dd8\u0dd9\u0dda\u0ddb\u0ddc\u0ddd\u0dde\u0ddf\u0df2\u0df3\u0f3e\u0f3f\u0f7f\u102c\u1031\u1038\u1056\u1057\u17b6\u17be\u17bf\u17c0\u17c1\u17c2\u17c3\u17c4\u17c5\u17c7\u17c8\u1923\u1924\u1925\u1926\u1929\u192a\u192b\u1930\u1931\u1933\u1934\u1935\u1936\u1937\u1938\u19b0\u19b1\u19b2\u19b3\u19b4\u19b5\u19b6\u19b7\u19b8\u19b9\u19ba\u19bb\u19bc\u19bd\u19be\u19bf\u19c0\u19c8\u19c9\u1a19\u1a1a\u1a1b\ua802\ua823\ua824\ua827'
+
+Me = u'\u0488\u0489\u06de\u20dd\u20de\u20df\u20e0\u20e2\u20e3\u20e4'
+
+Mn = u'\u0300\u0301\u0302\u0303\u0304\u0305\u0306\u0307\u0308\u0309\u030a\u030b\u030c\u030d\u030e\u030f\u0310\u0311\u0312\u0313\u0314\u0315\u0316\u0317\u0318\u0319\u031a\u031b\u031c\u031d\u031e\u031f\u0320\u0321\u0322\u0323\u0324\u0325\u0326\u0327\u0328\u0329\u032a\u032b\u032c\u032d\u032e\u032f\u0330\u0331\u0332\u0333\u0334\u0335\u0336\u0337\u0338\u0339\u033a\u033b\u033c\u033d\u033e\u033f\u0340\u0341\u0342\u0343\u0344\u0345\u0346\u0347\u0348\u0349\u034a\u034b\u034c\u034d\u034e\u034f\u0350\u0351\u0352\u0353\u0354\u0355\u0356\u0357\u0358\u0359\u035a\u035b\u035c\u035d\u035e\u035f\u0360\u0361\u0362\u0363\u0364\u0365\u0366\u0367\u0368\u0369\u036a\u036b\u036c\u036d\u036e\u036f\u0483\u0484\u0485\u0486\u0591\u0592\u0593\u0594\u0595\u0596\u0597\u0598\u0599\u059a\u059b\u059c\u059d\u059e\u059f\u05a0\u05a1\u05a2\u05a3\u05a4\u05a5\u05a6\u05a7\u05a8\u05a9\u05aa\u05ab\u05ac\u05ad\u05ae\u05af\u05b0\u05b1\u05b2\u05b3\u05b4\u05b5\u05b6\u05b7\u05b8\u05b9\u05bb\u05bc\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610\u0611\u0612\u0613\u0614\u0615\u064b\u064c\u064d\u064e\u064f\u0650\u0651\u0652\u0653\u0654\u0655\u0656\u0657\u0658\u0659\u065a\u065b\u065c\u065d\u065e\u0670\u06d6\u06d7\u06d8\u06d9\u06da\u06db\u06dc\u06df\u06e0\u06e1\u06e2\u06e3\u06e4\u06e7\u06e8\u06ea\u06eb\u06ec\u06ed\u0711\u0730\u0731\u0732\u0733\u0734\u0735\u0736\u0737\u0738\u0739\u073a\u073b\u073c\u073d\u073e\u073f\u0740\u0741\u0742\u0743\u0744\u0745\u0746\u0747\u0748\u0749\u074a\u07a6\u07a7\u07a8\u07a9\u07aa\u07ab\u07ac\u07ad\u07ae\u07af\u07b0\u0901\u0902\u093c\u0941\u0942\u0943\u0944\u0945\u0946\u0947\u0948\u094d\u0951\u0952\u0953\u0954\u0962\u0963\u0981\u09bc\u09c1\u09c2\u09c3\u09c4\u09cd\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b\u0a4c\u0a4d\u0a70\u0a71\u0a81\u0a82\u0abc\u0ac1\u0ac2\u0ac3\u0ac4\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3f\u0b41\u0b42\u0b43\u0b4d\u0b56\u0b82\u0bc0\u0bcd\u0c3e\u0c3f\u0c40\u0c46\u0c47\u0c48\u0c4a\u0c4b\u0c4c\u0c4d\u0c55\u0c56\u0cbc\u0cbf\u0cc6\u0ccc\u0ccd\u0d41\u0d42\u0d43\u0d4d\u0dca\u0dd2\u0dd3\u0dd4\u0dd6\u0e31\u0e34\u0e35\u0e36\u0e37\u0e38\u0e39\u0e3a\u0e47\u0e48\u0e49\u0e4a\u0e4b\u0e4c\u0e4d\u0e4e\u0eb1\u0eb4\u0eb5\u0eb6\u0eb7\u0eb8\u0eb9\u0ebb\u0ebc\u0ec8\u0ec9\u0eca\u0ecb\u0ecc\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71\u0f72\u0f73\u0f74\u0f75\u0f76\u0f77\u0f78\u0f79\u0f7a\u0f7b\u0f7c\u0f7d\u0f7e\u0f80\u0f81\u0f82\u0f83\u0f84\u0f86\u0f87\u0f90\u0f91\u0f92\u0f93\u0f94\u0f95\u0f96\u0f97\u0f99\u0f9a\u0f9b\u0f9c\u0f9d\u0f9e\u0f9f\u0fa0\u0fa1\u0fa2\u0fa3\u0fa4\u0fa5\u0fa6\u0fa7\u0fa8\u0fa9\u0faa\u0fab\u0fac\u0fad\u0fae\u0faf\u0fb0\u0fb1\u0fb2\u0fb3\u0fb4\u0fb5\u0fb6\u0fb7\u0fb8\u0fb9\u0fba\u0fbb\u0fbc\u0fc6\u102d\u102e\u102f\u1030\u1032\u1036\u1037\u1039\u1058\u1059\u135f\u1712\u1713\u1714\u1732\u1733\u1734\u1752\u1753\u1772\u1773\u17b7\u17b8\u17b9\u17ba\u17bb\u17bc\u17bd\u17c6\u17c9\u17ca\u17cb\u17cc\u17cd\u17ce\u17cf\u17d0\u17d1\u17d2\u17d3\u17dd\u180b\u180c\u180d\u18a9\u1920\u1921\u1922\u1927\u1928\u1932\u1939\u193a\u193b\u1a17\u1a18\u1dc0\u1dc1\u1dc2\u1dc3\u20d0\u20d1\u20d2\u20d3\u20d4\u20d5\u20d6\u20d7\u20d8\u20d9\u20da\u20db\u20dc\u20e1\u20e5\u20e6\u20e7\u20e8\u20e9\u20ea\u20eb\u302a\u302b\u302c\u302d\u302e\u302f\u3099\u309a\ua806\ua80b\ua825\ua826\ufb1e\ufe00\ufe01\ufe02\ufe03\ufe04\ufe05\ufe06\ufe07\ufe08\ufe09\ufe0a\ufe0b\ufe0c\ufe0d\ufe0e\ufe0f\ufe20\ufe21\ufe22\ufe23'
+
+Nd = u'0123456789\u0660\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669\u06f0\u06f1\u06f2\u06f3\u06f4\u06f5\u06f6\u06f7\u06f8\u06f9\u0966\u0967\u0968\u0969\u096a\u096b\u096c\u096d\u096e\u096f\u09e6\u09e7\u09e8\u09e9\u09ea\u09eb\u09ec\u09ed\u09ee\u09ef\u0a66\u0a67\u0a68\u0a69\u0a6a\u0a6b\u0a6c\u0a6d\u0a6e\u0a6f\u0ae6\u0ae7\u0ae8\u0ae9\u0aea\u0aeb\u0aec\u0aed\u0aee\u0aef\u0b66\u0b67\u0b68\u0b69\u0b6a\u0b6b\u0b6c\u0b6d\u0b6e\u0b6f\u0be6\u0be7\u0be8\u0be9\u0bea\u0beb\u0bec\u0bed\u0bee\u0bef\u0c66\u0c67\u0c68\u0c69\u0c6a\u0c6b\u0c6c\u0c6d\u0c6e\u0c6f\u0ce6\u0ce7\u0ce8\u0ce9\u0cea\u0ceb\u0cec\u0ced\u0cee\u0cef\u0d66\u0d67\u0d68\u0d69\u0d6a\u0d6b\u0d6c\u0d6d\u0d6e\u0d6f\u0e50\u0e51\u0e52\u0e53\u0e54\u0e55\u0e56\u0e57\u0e58\u0e59\u0ed0\u0ed1\u0ed2\u0ed3\u0ed4\u0ed5\u0ed6\u0ed7\u0ed8\u0ed9\u0f20\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\u0f29\u1040\u1041\u1042\u1043\u1044\u1045\u1046\u1047\u1048\u1049\u17e0\u17e1\u17e2\u17e3\u17e4\u17e5\u17e6\u17e7\u17e8\u17e9\u1810\u1811\u1812\u1813\u1814\u1815\u1816\u1817\u1818\u1819\u1946\u1947\u1948\u1949\u194a\u194b\u194c\u194d\u194e\u194f\u19d0\u19d1\u19d2\u19d3\u19d4\u19d5\u19d6\u19d7\u19d8\u19d9\uff10\uff11\uff12\uff13\uff14\uff15\uff16\uff17\uff18\uff19'
+
+Nl = u'\u16ee\u16ef\u16f0\u2160\u2161\u2162\u2163\u2164\u2165\u2166\u2167\u2168\u2169\u216a\u216b\u216c\u216d\u216e\u216f\u2170\u2171\u2172\u2173\u2174\u2175\u2176\u2177\u2178\u2179\u217a\u217b\u217c\u217d\u217e\u217f\u2180\u2181\u2182\u2183\u3007\u3021\u3022\u3023\u3024\u3025\u3026\u3027\u3028\u3029\u3038\u3039\u303a'
+
+No = u'\xb2\xb3\xb9\xbc\xbd\xbe\u09f4\u09f5\u09f6\u09f7\u09f8\u09f9\u0bf0\u0bf1\u0bf2\u0f2a\u0f2b\u0f2c\u0f2d\u0f2e\u0f2f\u0f30\u0f31\u0f32\u0f33\u1369\u136a\u136b\u136c\u136d\u136e\u136f\u1370\u1371\u1372\u1373\u1374\u1375\u1376\u1377\u1378\u1379\u137a\u137b\u137c\u17f0\u17f1\u17f2\u17f3\u17f4\u17f5\u17f6\u17f7\u17f8\u17f9\u2070\u2074\u2075\u2076\u2077\u2078\u2079\u2080\u2081\u2082\u2083\u2084\u2085\u2086\u2087\u2088\u2089\u2153\u2154\u2155\u2156\u2157\u2158\u2159\u215a\u215b\u215c\u215d\u215e\u215f\u2460\u2461\u2462\u2463\u2464\u2465\u2466\u2467\u2468\u2469\u246a\u246b\u246c\u246d\u246e\u246f\u2470\u2471\u2472\u2473\u2474\u2475\u2476\u2477\u2478\u2479\u247a\u247b\u247c\u247d\u247e\u247f\u2480\u2481\u2482\u2483\u2484\u2485\u2486\u2487\u2488\u2489\u248a\u248b\u248c\u248d\u248e\u248f\u2490\u2491\u2492\u2493\u2494\u2495\u2496\u2497\u2498\u2499\u249a\u249b\u24ea\u24eb\u24ec\u24ed\u24ee\u24ef\u24f0\u24f1\u24f2\u24f3\u24f4\u24f5\u24f6\u24f7\u24f8\u24f9\u24fa\u24fb\u24fc\u24fd\u24fe\u24ff\u2776\u2777\u2778\u2779\u277a\u277b\u277c\u277d\u277e\u277f\u2780\u2781\u2782\u2783\u2784\u2785\u2786\u2787\u2788\u2789\u278a\u278b\u278c\u278d\u278e\u278f\u2790\u2791\u2792\u2793\u2cfd\u3192\u3193\u3194\u3195\u3220\u3221\u3222\u3223\u3224\u3225\u3226\u3227\u3228\u3229\u3251\u3252\u3253\u3254\u3255\u3256\u3257\u3258\u3259\u325a\u325b\u325c\u325d\u325e\u325f\u3280\u3281\u3282\u3283\u3284\u3285\u3286\u3287\u3288\u3289\u32b1\u32b2\u32b3\u32b4\u32b5\u32b6\u32b7\u32b8\u32b9\u32ba\u32bb\u32bc\u32bd\u32be\u32bf'
+
+Pc = u'_\u203f\u2040\u2054\ufe33\ufe34\ufe4d\ufe4e\ufe4f\uff3f'
+
+Pd = u'-\u058a\u1806\u2010\u2011\u2012\u2013\u2014\u2015\u2e17\u301c\u3030\u30a0\ufe31\ufe32\ufe58\ufe63\uff0d'
+
+Pe = u')]}\u0f3b\u0f3d\u169c\u2046\u207e\u208e\u232a\u23b5\u2769\u276b\u276d\u276f\u2771\u2773\u2775\u27c6\u27e7\u27e9\u27eb\u2984\u2986\u2988\u298a\u298c\u298e\u2990\u2992\u2994\u2996\u2998\u29d9\u29db\u29fd\u3009\u300b\u300d\u300f\u3011\u3015\u3017\u3019\u301b\u301e\u301f\ufd3f\ufe18\ufe36\ufe38\ufe3a\ufe3c\ufe3e\ufe40\ufe42\ufe44\ufe48\ufe5a\ufe5c\ufe5e\uff09\uff3d\uff5d\uff60\uff63'
+
+Pf = u'\xbb\u2019\u201d\u203a\u2e03\u2e05\u2e0a\u2e0d\u2e1d'
+
+Pi = u'\xab\u2018\u201b\u201c\u201f\u2039\u2e02\u2e04\u2e09\u2e0c\u2e1c'
+
+Po = u'!"#%&\'*,./:;?@\\\xa1\xb7\xbf\u037e\u0387\u055a\u055b\u055c\u055d\u055e\u055f\u0589\u05be\u05c0\u05c3\u05c6\u05f3\u05f4\u060c\u060d\u061b\u061e\u061f\u066a\u066b\u066c\u066d\u06d4\u0700\u0701\u0702\u0703\u0704\u0705\u0706\u0707\u0708\u0709\u070a\u070b\u070c\u070d\u0964\u0965\u0970\u0df4\u0e4f\u0e5a\u0e5b\u0f04\u0f05\u0f06\u0f07\u0f08\u0f09\u0f0a\u0f0b\u0f0c\u0f0d\u0f0e\u0f0f\u0f10\u0f11\u0f12\u0f85\u0fd0\u0fd1\u104a\u104b\u104c\u104d\u104e\u104f\u10fb\u1361\u1362\u1363\u1364\u1365\u1366\u1367\u1368\u166d\u166e\u16eb\u16ec\u16ed\u1735\u1736\u17d4\u17d5\u17d6\u17d8\u17d9\u17da\u1800\u1801\u1802\u1803\u1804\u1805\u1807\u1808\u1809\u180a\u1944\u1945\u19de\u19df\u1a1e\u1a1f\u2016\u2017\u2020\u2021\u2022\u2023\u2024\u2025\u2026\u2027\u2030\u2031\u2032\u2033\u2034\u2035\u2036\u2037\u2038\u203b\u203c\u203d\u203e\u2041\u2042\u2043\u2047\u2048\u2049\u204a\u204b\u204c\u204d\u204e\u204f\u2050\u2051\u2053\u2055\u2056\u2057\u2058\u2059\u205a\u205b\u205c\u205d\u205e\u23b6\u2cf9\u2cfa\u2cfb\u2cfc\u2cfe\u2cff\u2e00\u2e01\u2e06\u2e07\u2e08\u2e0b\u2e0e\u2e0f\u2e10\u2e11\u2e12\u2e13\u2e14\u2e15\u2e16\u3001\u3002\u3003\u303d\u30fb\ufe10\ufe11\ufe12\ufe13\ufe14\ufe15\ufe16\ufe19\ufe30\ufe45\ufe46\ufe49\ufe4a\ufe4b\ufe4c\ufe50\ufe51\ufe52\ufe54\ufe55\ufe56\ufe57\ufe5f\ufe60\ufe61\ufe68\ufe6a\ufe6b\uff01\uff02\uff03\uff05\uff06\uff07\uff0a\uff0c\uff0e\uff0f\uff1a\uff1b\uff1f\uff20\uff3c\uff61\uff64\uff65'
+
+Ps = u'([{\u0f3a\u0f3c\u169b\u201a\u201e\u2045\u207d\u208d\u2329\u23b4\u2768\u276a\u276c\u276e\u2770\u2772\u2774\u27c5\u27e6\u27e8\u27ea\u2983\u2985\u2987\u2989\u298b\u298d\u298f\u2991\u2993\u2995\u2997\u29d8\u29da\u29fc\u3008\u300a\u300c\u300e\u3010\u3014\u3016\u3018\u301a\u301d\ufd3e\ufe17\ufe35\ufe37\ufe39\ufe3b\ufe3d\ufe3f\ufe41\ufe43\ufe47\ufe59\ufe5b\ufe5d\uff08\uff3b\uff5b\uff5f\uff62'
+
+Sc = u'$\xa2\xa3\xa4\xa5\u060b\u09f2\u09f3\u0af1\u0bf9\u0e3f\u17db\u20a0\u20a1\u20a2\u20a3\u20a4\u20a5\u20a6\u20a7\u20a8\u20a9\u20aa\u20ab\u20ac\u20ad\u20ae\u20af\u20b0\u20b1\u20b2\u20b3\u20b4\u20b5\ufdfc\ufe69\uff04\uffe0\uffe1\uffe5\uffe6'
+
+Sk = u'^`\xa8\xaf\xb4\xb8\u02c2\u02c3\u02c4\u02c5\u02d2\u02d3\u02d4\u02d5\u02d6\u02d7\u02d8\u02d9\u02da\u02db\u02dc\u02dd\u02de\u02df\u02e5\u02e6\u02e7\u02e8\u02e9\u02ea\u02eb\u02ec\u02ed\u02ef\u02f0\u02f1\u02f2\u02f3\u02f4\u02f5\u02f6\u02f7\u02f8\u02f9\u02fa\u02fb\u02fc\u02fd\u02fe\u02ff\u0374\u0375\u0384\u0385\u1fbd\u1fbf\u1fc0\u1fc1\u1fcd\u1fce\u1fcf\u1fdd\u1fde\u1fdf\u1fed\u1fee\u1fef\u1ffd\u1ffe\u309b\u309c\ua700\ua701\ua702\ua703\ua704\ua705\ua706\ua707\ua708\ua709\ua70a\ua70b\ua70c\ua70d\ua70e\ua70f\ua710\ua711\ua712\ua713\ua714\ua715\ua716\uff3e\uff40\uffe3'
+
+Sm = u'+<=>|~\xac\xb1\xd7\xf7\u03f6\u2044\u2052\u207a\u207b\u207c\u208a\u208b\u208c\u2140\u2141\u2142\u2143\u2144\u214b\u2190\u2191\u2192\u2193\u2194\u219a\u219b\u21a0\u21a3\u21a6\u21ae\u21ce\u21cf\u21d2\u21d4\u21f4\u21f5\u21f6\u21f7\u21f8\u21f9\u21fa\u21fb\u21fc\u21fd\u21fe\u21ff\u2200\u2201\u2202\u2203\u2204\u2205\u2206\u2207\u2208\u2209\u220a\u220b\u220c\u220d\u220e\u220f\u2210\u2211\u2212\u2213\u2214\u2215\u2216\u2217\u2218\u2219\u221a\u221b\u221c\u221d\u221e\u221f\u2220\u2221\u2222\u2223\u2224\u2225\u2226\u2227\u2228\u2229\u222a\u222b\u222c\u222d\u222e\u222f\u2230\u2231\u2232\u2233\u2234\u2235\u2236\u2237\u2238\u2239\u223a\u223b\u223c\u223d\u223e\u223f\u2240\u2241\u2242\u2243\u2244\u2245\u2246\u2247\u2248\u2249\u224a\u224b\u224c\u224d\u224e\u224f\u2250\u2251\u2252\u2253\u2254\u2255\u2256\u2257\u2258\u2259\u225a\u225b\u225c\u225d\u225e\u225f\u2260\u2261\u2262\u2263\u2264\u2265\u2266\u2267\u2268\u2269\u226a\u226b\u226c\u226d\u226e\u226f\u2270\u2271\u2272\u2273\u2274\u2275\u2276\u2277\u2278\u2279\u227a\u227b\u227c\u227d\u227e\u227f\u2280\u2281\u2282\u2283\u2284\u2285\u2286\u2287\u2288\u2289\u228a\u228b\u228c\u228d\u228e\u228f\u2290\u2291\u2292\u2293\u2294\u2295\u2296\u2297\u2298\u2299\u229a\u229b\u229c\u229d\u229e\u229f\u22a0\u22a1\u22a2\u22a3\u22a4\u22a5\u22a6\u22a7\u22a8\u22a9\u22aa\u22ab\u22ac\u22ad\u22ae\u22af\u22b0\u22b1\u22b2\u22b3\u22b4\u22b5\u22b6\u22b7\u22b8\u22b9\u22ba\u22bb\u22bc\u22bd\u22be\u22bf\u22c0\u22c1\u22c2\u22c3\u22c4\u22c5\u22c6\u22c7\u22c8\u22c9\u22ca\u22cb\u22cc\u22cd\u22ce\u22cf\u22d0\u22d1\u22d2\u22d3\u22d4\u22d5\u22d6\u22d7\u22d8\u22d9\u22da\u22db\u22dc\u22dd\u22de\u22df\u22e0\u22e1\u22e2\u22e3\u22e4\u22e5\u22e6\u22e7\u22e8\u22e9\u22ea\u22eb\u22ec\u22ed\u22ee\u22ef\u22f0\u22f1\u22f2\u22f3\u22f4\u22f5\u22f6\u22f7\u22f8\u22f9\u22fa\u22fb\u22fc\u22fd\u22fe\u22ff\u2308\u2309\u230a\u230b\u2320\u2321\u237c\u239b\u239c\u239d\u239e\u239f\u23a0\u23a1\u23a2\u23a3\u23a4\u23a5\u23a6\u23a7\u23a8\u23a9\u23aa\u23ab\u23ac\u23ad\u23ae\u23af\u23b0\u23b1\u23b2\u23b3\u25b7\u25c1\u25f8\u25f9\u25fa\u25fb\u25fc\u25fd\u25fe\u25ff\u266f\u27c0\u27c1\u27c2\u27c3\u27c4\u27d0\u27d1\u27d2\u27d3\u27d4\u27d5\u27d6\u27d7\u27d8\u27d9\u27da\u27db\u27dc\u27dd\u27de\u27df\u27e0\u27e1\u27e2\u27e3\u27e4\u27e5\u27f0\u27f1\u27f2\u27f3\u27f4\u27f5\u27f6\u27f7\u27f8\u27f9\u27fa\u27fb\u27fc\u27fd\u27fe\u27ff\u2900\u2901\u2902\u2903\u2904\u2905\u2906\u2907\u2908\u2909\u290a\u290b\u290c\u290d\u290e\u290f\u2910\u2911\u2912\u2913\u2914\u2915\u2916\u2917\u2918\u2919\u291a\u291b\u291c\u291d\u291e\u291f\u2920\u2921\u2922\u2923\u2924\u2925\u2926\u2927\u2928\u2929\u292a\u292b\u292c\u292d\u292e\u292f\u2930\u2931\u2932\u2933\u2934\u2935\u2936\u2937\u2938\u2939\u293a\u293b\u293c\u293d\u293e\u293f\u2940\u2941\u2942\u2943\u2944\u2945\u2946\u2947\u2948\u2949\u294a\u294b\u294c\u294d\u294e\u294f\u2950\u2951\u2952\u2953\u2954\u2955\u2956\u2957\u2958\u2959\u295a\u295b\u295c\u295d\u295e\u295f\u2960\u2961\u2962\u2963\u2964\u2965\u2966\u2967\u2968\u2969\u296a\u296b\u296c\u296d\u296e\u296f\u2970\u2971\u2972\u2973\u2974\u2975\u2976\u2977\u2978\u2979\u297a\u297b\u297c\u297d\u297e\u297f\u2980\u2981\u2982\u2999\u299a\u299b\u299c\u299d\u299e\u299f\u29a0\u29a1\u29a2\u29a3\u29a4\u29a5\u29a6\u29a7\u29a8\u29a9\u29aa\u29ab\u29ac\u29ad\u29ae\u29af\u29b0\u29b1\u29b2\u29b3\u29b4\u29b5\u29b6\u29b7\u29b8\u29b9\u29ba\u29bb\u29bc\u29bd\u29be\u29bf\u29c0\u29c1\u29c2\u29c3\u29c4\u29c5\u29c6\u29c7\u29c8\u29c9\u29ca\u29cb\u29cc\u29cd\u29ce\u29cf\u29d0\u29d1\u29d2\u29d3\u29d4\u29d5\u29d6\u29d7\u29dc\u29dd\u29de\u29df\u29e0\u29e1\u29e2\u29e3\u29e4\u29e5\u29e6\u29e7\u29e8\u29e9\u29ea\u29eb\u29ec\u29ed\u29ee\u29ef\u29f0\u29f1\u29f2\u29f3\u29f4\u29f5\u29f6\u29f7\u29f8\u29f9\u29fa\u29fb\u29fe\u29ff\u2a00\u2a01\u2a02\u2a03\u2a04\u2a05\u2a06\u2a07\u2a08\u2a09\u2a0a\u2a0b\u2a0c\u2a0d\u2a0e\u2a0f\u2a10\u2a11\u2a12\u2a13\u2a14\u2a15\u2a16\u2a17\u2a18\u2a19\u2a1a\u2a1b\u2a1c\u2a1d\u2a1e\u2a1f\u2a20\u2a21\u2a22\u2a23\u2a24\u2a25\u2a26\u2a27\u2a28\u2a29\u2a2a\u2a2b\u2a2c\u2a2d\u2a2e\u2a2f\u2a30\u2a31\u2a32\u2a33\u2a34\u2a35\u2a36\u2a37\u2a38\u2a39\u2a3a\u2a3b\u2a3c\u2a3d\u2a3e\u2a3f\u2a40\u2a41\u2a42\u2a43\u2a44\u2a45\u2a46\u2a47\u2a48\u2a49\u2a4a\u2a4b\u2a4c\u2a4d\u2a4e\u2a4f\u2a50\u2a51\u2a52\u2a53\u2a54\u2a55\u2a56\u2a57\u2a58\u2a59\u2a5a\u2a5b\u2a5c\u2a5d\u2a5e\u2a5f\u2a60\u2a61\u2a62\u2a63\u2a64\u2a65\u2a66\u2a67\u2a68\u2a69\u2a6a\u2a6b\u2a6c\u2a6d\u2a6e\u2a6f\u2a70\u2a71\u2a72\u2a73\u2a74\u2a75\u2a76\u2a77\u2a78\u2a79\u2a7a\u2a7b\u2a7c\u2a7d\u2a7e\u2a7f\u2a80\u2a81\u2a82\u2a83\u2a84\u2a85\u2a86\u2a87\u2a88\u2a89\u2a8a\u2a8b\u2a8c\u2a8d\u2a8e\u2a8f\u2a90\u2a91\u2a92\u2a93\u2a94\u2a95\u2a96\u2a97\u2a98\u2a99\u2a9a\u2a9b\u2a9c\u2a9d\u2a9e\u2a9f\u2aa0\u2aa1\u2aa2\u2aa3\u2aa4\u2aa5\u2aa6\u2aa7\u2aa8\u2aa9\u2aaa\u2aab\u2aac\u2aad\u2aae\u2aaf\u2ab0\u2ab1\u2ab2\u2ab3\u2ab4\u2ab5\u2ab6\u2ab7\u2ab8\u2ab9\u2aba\u2abb\u2abc\u2abd\u2abe\u2abf\u2ac0\u2ac1\u2ac2\u2ac3\u2ac4\u2ac5\u2ac6\u2ac7\u2ac8\u2ac9\u2aca\u2acb\u2acc\u2acd\u2ace\u2acf\u2ad0\u2ad1\u2ad2\u2ad3\u2ad4\u2ad5\u2ad6\u2ad7\u2ad8\u2ad9\u2ada\u2adb\u2adc\u2add\u2ade\u2adf\u2ae0\u2ae1\u2ae2\u2ae3\u2ae4\u2ae5\u2ae6\u2ae7\u2ae8\u2ae9\u2aea\u2aeb\u2aec\u2aed\u2aee\u2aef\u2af0\u2af1\u2af2\u2af3\u2af4\u2af5\u2af6\u2af7\u2af8\u2af9\u2afa\u2afb\u2afc\u2afd\u2afe\u2aff\ufb29\ufe62\ufe64\ufe65\ufe66\uff0b\uff1c\uff1d\uff1e\uff5c\uff5e\uffe2\uffe9\uffea\uffeb\uffec'
+
+So = u'\xa6\xa7\xa9\xae\xb0\xb6\u0482\u060e\u060f\u06e9\u06fd\u06fe\u09fa\u0b70\u0bf3\u0bf4\u0bf5\u0bf6\u0bf7\u0bf8\u0bfa\u0f01\u0f02\u0f03\u0f13\u0f14\u0f15\u0f16\u0f17\u0f1a\u0f1b\u0f1c\u0f1d\u0f1e\u0f1f\u0f34\u0f36\u0f38\u0fbe\u0fbf\u0fc0\u0fc1\u0fc2\u0fc3\u0fc4\u0fc5\u0fc7\u0fc8\u0fc9\u0fca\u0fcb\u0fcc\u0fcf\u1360\u1390\u1391\u1392\u1393\u1394\u1395\u1396\u1397\u1398\u1399\u1940\u19e0\u19e1\u19e2\u19e3\u19e4\u19e5\u19e6\u19e7\u19e8\u19e9\u19ea\u19eb\u19ec\u19ed\u19ee\u19ef\u19f0\u19f1\u19f2\u19f3\u19f4\u19f5\u19f6\u19f7\u19f8\u19f9\u19fa\u19fb\u19fc\u19fd\u19fe\u19ff\u2100\u2101\u2103\u2104\u2105\u2106\u2108\u2109\u2114\u2116\u2117\u2118\u211e\u211f\u2120\u2121\u2122\u2123\u2125\u2127\u2129\u212e\u2132\u213a\u213b\u214a\u214c\u2195\u2196\u2197\u2198\u2199\u219c\u219d\u219e\u219f\u21a1\u21a2\u21a4\u21a5\u21a7\u21a8\u21a9\u21aa\u21ab\u21ac\u21ad\u21af\u21b0\u21b1\u21b2\u21b3\u21b4\u21b5\u21b6\u21b7\u21b8\u21b9\u21ba\u21bb\u21bc\u21bd\u21be\u21bf\u21c0\u21c1\u21c2\u21c3\u21c4\u21c5\u21c6\u21c7\u21c8\u21c9\u21ca\u21cb\u21cc\u21cd\u21d0\u21d1\u21d3\u21d5\u21d6\u21d7\u21d8\u21d9\u21da\u21db\u21dc\u21dd\u21de\u21df\u21e0\u21e1\u21e2\u21e3\u21e4\u21e5\u21e6\u21e7\u21e8\u21e9\u21ea\u21eb\u21ec\u21ed\u21ee\u21ef\u21f0\u21f1\u21f2\u21f3\u2300\u2301\u2302\u2303\u2304\u2305\u2306\u2307\u230c\u230d\u230e\u230f\u2310\u2311\u2312\u2313\u2314\u2315\u2316\u2317\u2318\u2319\u231a\u231b\u231c\u231d\u231e\u231f\u2322\u2323\u2324\u2325\u2326\u2327\u2328\u232b\u232c\u232d\u232e\u232f\u2330\u2331\u2332\u2333\u2334\u2335\u2336\u2337\u2338\u2339\u233a\u233b\u233c\u233d\u233e\u233f\u2340\u2341\u2342\u2343\u2344\u2345\u2346\u2347\u2348\u2349\u234a\u234b\u234c\u234d\u234e\u234f\u2350\u2351\u2352\u2353\u2354\u2355\u2356\u2357\u2358\u2359\u235a\u235b\u235c\u235d\u235e\u235f\u2360\u2361\u2362\u2363\u2364\u2365\u2366\u2367\u2368\u2369\u236a\u236b\u236c\u236d\u236e\u236f\u2370\u2371\u2372\u2373\u2374\u2375\u2376\u2377\u2378\u2379\u237a\u237b\u237d\u237e\u237f\u2380\u2381\u2382\u2383\u2384\u2385\u2386\u2387\u2388\u2389\u238a\u238b\u238c\u238d\u238e\u238f\u2390\u2391\u2392\u2393\u2394\u2395\u2396\u2397\u2398\u2399\u239a\u23b7\u23b8\u23b9\u23ba\u23bb\u23bc\u23bd\u23be\u23bf\u23c0\u23c1\u23c2\u23c3\u23c4\u23c5\u23c6\u23c7\u23c8\u23c9\u23ca\u23cb\u23cc\u23cd\u23ce\u23cf\u23d0\u23d1\u23d2\u23d3\u23d4\u23d5\u23d6\u23d7\u23d8\u23d9\u23da\u23db\u2400\u2401\u2402\u2403\u2404\u2405\u2406\u2407\u2408\u2409\u240a\u240b\u240c\u240d\u240e\u240f\u2410\u2411\u2412\u2413\u2414\u2415\u2416\u2417\u2418\u2419\u241a\u241b\u241c\u241d\u241e\u241f\u2420\u2421\u2422\u2423\u2424\u2425\u2426\u2440\u2441\u2442\u2443\u2444\u2445\u2446\u2447\u2448\u2449\u244a\u249c\u249d\u249e\u249f\u24a0\u24a1\u24a2\u24a3\u24a4\u24a5\u24a6\u24a7\u24a8\u24a9\u24aa\u24ab\u24ac\u24ad\u24ae\u24af\u24b0\u24b1\u24b2\u24b3\u24b4\u24b5\u24b6\u24b7\u24b8\u24b9\u24ba\u24bb\u24bc\u24bd\u24be\u24bf\u24c0\u24c1\u24c2\u24c3\u24c4\u24c5\u24c6\u24c7\u24c8\u24c9\u24ca\u24cb\u24cc\u24cd\u24ce\u24cf\u24d0\u24d1\u24d2\u24d3\u24d4\u24d5\u24d6\u24d7\u24d8\u24d9\u24da\u24db\u24dc\u24dd\u24de\u24df\u24e0\u24e1\u24e2\u24e3\u24e4\u24e5\u24e6\u24e7\u24e8\u24e9\u2500\u2501\u2502\u2503\u2504\u2505\u2506\u2507\u2508\u2509\u250a\u250b\u250c\u250d\u250e\u250f\u2510\u2511\u2512\u2513\u2514\u2515\u2516\u2517\u2518\u2519\u251a\u251b\u251c\u251d\u251e\u251f\u2520\u2521\u2522\u2523\u2524\u2525\u2526\u2527\u2528\u2529\u252a\u252b\u252c\u252d\u252e\u252f\u2530\u2531\u2532\u2533\u2534\u2535\u2536\u2537\u2538\u2539\u253a\u253b\u253c\u253d\u253e\u253f\u2540\u2541\u2542\u2543\u2544\u2545\u2546\u2547\u2548\u2549\u254a\u254b\u254c\u254d\u254e\u254f\u2550\u2551\u2552\u2553\u2554\u2555\u2556\u2557\u2558\u2559\u255a\u255b\u255c\u255d\u255e\u255f\u2560\u2561\u2562\u2563\u2564\u2565\u2566\u2567\u2568\u2569\u256a\u256b\u256c\u256d\u256e\u256f\u2570\u2571\u2572\u2573\u2574\u2575\u2576\u2577\u2578\u2579\u257a\u257b\u257c\u257d\u257e\u257f\u2580\u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2588\u2589\u258a\u258b\u258c\u258d\u258e\u258f\u2590\u2591\u2592\u2593\u2594\u2595\u2596\u2597\u2598\u2599\u259a\u259b\u259c\u259d\u259e\u259f\u25a0\u25a1\u25a2\u25a3\u25a4\u25a5\u25a6\u25a7\u25a8\u25a9\u25aa\u25ab\u25ac\u25ad\u25ae\u25af\u25b0\u25b1\u25b2\u25b3\u25b4\u25b5\u25b6\u25b8\u25b9\u25ba\u25bb\u25bc\u25bd\u25be\u25bf\u25c0\u25c2\u25c3\u25c4\u25c5\u25c6\u25c7\u25c8\u25c9\u25ca\u25cb\u25cc\u25cd\u25ce\u25cf\u25d0\u25d1\u25d2\u25d3\u25d4\u25d5\u25d6\u25d7\u25d8\u25d9\u25da\u25db\u25dc\u25dd\u25de\u25df\u25e0\u25e1\u25e2\u25e3\u25e4\u25e5\u25e6\u25e7\u25e8\u25e9\u25ea\u25eb\u25ec\u25ed\u25ee\u25ef\u25f0\u25f1\u25f2\u25f3\u25f4\u25f5\u25f6\u25f7\u2600\u2601\u2602\u2603\u2604\u2605\u2606\u2607\u2608\u2609\u260a\u260b\u260c\u260d\u260e\u260f\u2610\u2611\u2612\u2613\u2614\u2615\u2616\u2617\u2618\u2619\u261a\u261b\u261c\u261d\u261e\u261f\u2620\u2621\u2622\u2623\u2624\u2625\u2626\u2627\u2628\u2629\u262a\u262b\u262c\u262d\u262e\u262f\u2630\u2631\u2632\u2633\u2634\u2635\u2636\u2637\u2638\u2639\u263a\u263b\u263c\u263d\u263e\u263f\u2640\u2641\u2642\u2643\u2644\u2645\u2646\u2647\u2648\u2649\u264a\u264b\u264c\u264d\u264e\u264f\u2650\u2651\u2652\u2653\u2654\u2655\u2656\u2657\u2658\u2659\u265a\u265b\u265c\u265d\u265e\u265f\u2660\u2661\u2662\u2663\u2664\u2665\u2666\u2667\u2668\u2669\u266a\u266b\u266c\u266d\u266e\u2670\u2671\u2672\u2673\u2674\u2675\u2676\u2677\u2678\u2679\u267a\u267b\u267c\u267d\u267e\u267f\u2680\u2681\u2682\u2683\u2684\u2685\u2686\u2687\u2688\u2689\u268a\u268b\u268c\u268d\u268e\u268f\u2690\u2691\u2692\u2693\u2694\u2695\u2696\u2697\u2698\u2699\u269a\u269b\u269c\u26a0\u26a1\u26a2\u26a3\u26a4\u26a5\u26a6\u26a7\u26a8\u26a9\u26aa\u26ab\u26ac\u26ad\u26ae\u26af\u26b0\u26b1\u2701\u2702\u2703\u2704\u2706\u2707\u2708\u2709\u270c\u270d\u270e\u270f\u2710\u2711\u2712\u2713\u2714\u2715\u2716\u2717\u2718\u2719\u271a\u271b\u271c\u271d\u271e\u271f\u2720\u2721\u2722\u2723\u2724\u2725\u2726\u2727\u2729\u272a\u272b\u272c\u272d\u272e\u272f\u2730\u2731\u2732\u2733\u2734\u2735\u2736\u2737\u2738\u2739\u273a\u273b\u273c\u273d\u273e\u273f\u2740\u2741\u2742\u2743\u2744\u2745\u2746\u2747\u2748\u2749\u274a\u274b\u274d\u274f\u2750\u2751\u2752\u2756\u2758\u2759\u275a\u275b\u275c\u275d\u275e\u2761\u2762\u2763\u2764\u2765\u2766\u2767\u2794\u2798\u2799\u279a\u279b\u279c\u279d\u279e\u279f\u27a0\u27a1\u27a2\u27a3\u27a4\u27a5\u27a6\u27a7\u27a8\u27a9\u27aa\u27ab\u27ac\u27ad\u27ae\u27af\u27b1\u27b2\u27b3\u27b4\u27b5\u27b6\u27b7\u27b8\u27b9\u27ba\u27bb\u27bc\u27bd\u27be\u2800\u2801\u2802\u2803\u2804\u2805\u2806\u2807\u2808\u2809\u280a\u280b\u280c\u280d\u280e\u280f\u2810\u2811\u2812\u2813\u2814\u2815\u2816\u2817\u2818\u2819\u281a\u281b\u281c\u281d\u281e\u281f\u2820\u2821\u2822\u2823\u2824\u2825\u2826\u2827\u2828\u2829\u282a\u282b\u282c\u282d\u282e\u282f\u2830\u2831\u2832\u2833\u2834\u2835\u2836\u2837\u2838\u2839\u283a\u283b\u283c\u283d\u283e\u283f\u2840\u2841\u2842\u2843\u2844\u2845\u2846\u2847\u2848\u2849\u284a\u284b\u284c\u284d\u284e\u284f\u2850\u2851\u2852\u2853\u2854\u2855\u2856\u2857\u2858\u2859\u285a\u285b\u285c\u285d\u285e\u285f\u2860\u2861\u2862\u2863\u2864\u2865\u2866\u2867\u2868\u2869\u286a\u286b\u286c\u286d\u286e\u286f\u2870\u2871\u2872\u2873\u2874\u2875\u2876\u2877\u2878\u2879\u287a\u287b\u287c\u287d\u287e\u287f\u2880\u2881\u2882\u2883\u2884\u2885\u2886\u2887\u2888\u2889\u288a\u288b\u288c\u288d\u288e\u288f\u2890\u2891\u2892\u2893\u2894\u2895\u2896\u2897\u2898\u2899\u289a\u289b\u289c\u289d\u289e\u289f\u28a0\u28a1\u28a2\u28a3\u28a4\u28a5\u28a6\u28a7\u28a8\u28a9\u28aa\u28ab\u28ac\u28ad\u28ae\u28af\u28b0\u28b1\u28b2\u28b3\u28b4\u28b5\u28b6\u28b7\u28b8\u28b9\u28ba\u28bb\u28bc\u28bd\u28be\u28bf\u28c0\u28c1\u28c2\u28c3\u28c4\u28c5\u28c6\u28c7\u28c8\u28c9\u28ca\u28cb\u28cc\u28cd\u28ce\u28cf\u28d0\u28d1\u28d2\u28d3\u28d4\u28d5\u28d6\u28d7\u28d8\u28d9\u28da\u28db\u28dc\u28dd\u28de\u28df\u28e0\u28e1\u28e2\u28e3\u28e4\u28e5\u28e6\u28e7\u28e8\u28e9\u28ea\u28eb\u28ec\u28ed\u28ee\u28ef\u28f0\u28f1\u28f2\u28f3\u28f4\u28f5\u28f6\u28f7\u28f8\u28f9\u28fa\u28fb\u28fc\u28fd\u28fe\u28ff\u2b00\u2b01\u2b02\u2b03\u2b04\u2b05\u2b06\u2b07\u2b08\u2b09\u2b0a\u2b0b\u2b0c\u2b0d\u2b0e\u2b0f\u2b10\u2b11\u2b12\u2b13\u2ce5\u2ce6\u2ce7\u2ce8\u2ce9\u2cea\u2e80\u2e81\u2e82\u2e83\u2e84\u2e85\u2e86\u2e87\u2e88\u2e89\u2e8a\u2e8b\u2e8c\u2e8d\u2e8e\u2e8f\u2e90\u2e91\u2e92\u2e93\u2e94\u2e95\u2e96\u2e97\u2e98\u2e99\u2e9b\u2e9c\u2e9d\u2e9e\u2e9f\u2ea0\u2ea1\u2ea2\u2ea3\u2ea4\u2ea5\u2ea6\u2ea7\u2ea8\u2ea9\u2eaa\u2eab\u2eac\u2ead\u2eae\u2eaf\u2eb0\u2eb1\u2eb2\u2eb3\u2eb4\u2eb5\u2eb6\u2eb7\u2eb8\u2eb9\u2eba\u2ebb\u2ebc\u2ebd\u2ebe\u2ebf\u2ec0\u2ec1\u2ec2\u2ec3\u2ec4\u2ec5\u2ec6\u2ec7\u2ec8\u2ec9\u2eca\u2ecb\u2ecc\u2ecd\u2ece\u2ecf\u2ed0\u2ed1\u2ed2\u2ed3\u2ed4\u2ed5\u2ed6\u2ed7\u2ed8\u2ed9\u2eda\u2edb\u2edc\u2edd\u2ede\u2edf\u2ee0\u2ee1\u2ee2\u2ee3\u2ee4\u2ee5\u2ee6\u2ee7\u2ee8\u2ee9\u2eea\u2eeb\u2eec\u2eed\u2eee\u2eef\u2ef0\u2ef1\u2ef2\u2ef3\u2f00\u2f01\u2f02\u2f03\u2f04\u2f05\u2f06\u2f07\u2f08\u2f09\u2f0a\u2f0b\u2f0c\u2f0d\u2f0e\u2f0f\u2f10\u2f11\u2f12\u2f13\u2f14\u2f15\u2f16\u2f17\u2f18\u2f19\u2f1a\u2f1b\u2f1c\u2f1d\u2f1e\u2f1f\u2f20\u2f21\u2f22\u2f23\u2f24\u2f25\u2f26\u2f27\u2f28\u2f29\u2f2a\u2f2b\u2f2c\u2f2d\u2f2e\u2f2f\u2f30\u2f31\u2f32\u2f33\u2f34\u2f35\u2f36\u2f37\u2f38\u2f39\u2f3a\u2f3b\u2f3c\u2f3d\u2f3e\u2f3f\u2f40\u2f41\u2f42\u2f43\u2f44\u2f45\u2f46\u2f47\u2f48\u2f49\u2f4a\u2f4b\u2f4c\u2f4d\u2f4e\u2f4f\u2f50\u2f51\u2f52\u2f53\u2f54\u2f55\u2f56\u2f57\u2f58\u2f59\u2f5a\u2f5b\u2f5c\u2f5d\u2f5e\u2f5f\u2f60\u2f61\u2f62\u2f63\u2f64\u2f65\u2f66\u2f67\u2f68\u2f69\u2f6a\u2f6b\u2f6c\u2f6d\u2f6e\u2f6f\u2f70\u2f71\u2f72\u2f73\u2f74\u2f75\u2f76\u2f77\u2f78\u2f79\u2f7a\u2f7b\u2f7c\u2f7d\u2f7e\u2f7f\u2f80\u2f81\u2f82\u2f83\u2f84\u2f85\u2f86\u2f87\u2f88\u2f89\u2f8a\u2f8b\u2f8c\u2f8d\u2f8e\u2f8f\u2f90\u2f91\u2f92\u2f93\u2f94\u2f95\u2f96\u2f97\u2f98\u2f99\u2f9a\u2f9b\u2f9c\u2f9d\u2f9e\u2f9f\u2fa0\u2fa1\u2fa2\u2fa3\u2fa4\u2fa5\u2fa6\u2fa7\u2fa8\u2fa9\u2faa\u2fab\u2fac\u2fad\u2fae\u2faf\u2fb0\u2fb1\u2fb2\u2fb3\u2fb4\u2fb5\u2fb6\u2fb7\u2fb8\u2fb9\u2fba\u2fbb\u2fbc\u2fbd\u2fbe\u2fbf\u2fc0\u2fc1\u2fc2\u2fc3\u2fc4\u2fc5\u2fc6\u2fc7\u2fc8\u2fc9\u2fca\u2fcb\u2fcc\u2fcd\u2fce\u2fcf\u2fd0\u2fd1\u2fd2\u2fd3\u2fd4\u2fd5\u2ff0\u2ff1\u2ff2\u2ff3\u2ff4\u2ff5\u2ff6\u2ff7\u2ff8\u2ff9\u2ffa\u2ffb\u3004\u3012\u3013\u3020\u3036\u3037\u303e\u303f\u3190\u3191\u3196\u3197\u3198\u3199\u319a\u319b\u319c\u319d\u319e\u319f\u31c0\u31c1\u31c2\u31c3\u31c4\u31c5\u31c6\u31c7\u31c8\u31c9\u31ca\u31cb\u31cc\u31cd\u31ce\u31cf\u3200\u3201\u3202\u3203\u3204\u3205\u3206\u3207\u3208\u3209\u320a\u320b\u320c\u320d\u320e\u320f\u3210\u3211\u3212\u3213\u3214\u3215\u3216\u3217\u3218\u3219\u321a\u321b\u321c\u321d\u321e\u322a\u322b\u322c\u322d\u322e\u322f\u3230\u3231\u3232\u3233\u3234\u3235\u3236\u3237\u3238\u3239\u323a\u323b\u323c\u323d\u323e\u323f\u3240\u3241\u3242\u3243\u3250\u3260\u3261\u3262\u3263\u3264\u3265\u3266\u3267\u3268\u3269\u326a\u326b\u326c\u326d\u326e\u326f\u3270\u3271\u3272\u3273\u3274\u3275\u3276\u3277\u3278\u3279\u327a\u327b\u327c\u327d\u327e\u327f\u328a\u328b\u328c\u328d\u328e\u328f\u3290\u3291\u3292\u3293\u3294\u3295\u3296\u3297\u3298\u3299\u329a\u329b\u329c\u329d\u329e\u329f\u32a0\u32a1\u32a2\u32a3\u32a4\u32a5\u32a6\u32a7\u32a8\u32a9\u32aa\u32ab\u32ac\u32ad\u32ae\u32af\u32b0\u32c0\u32c1\u32c2\u32c3\u32c4\u32c5\u32c6\u32c7\u32c8\u32c9\u32ca\u32cb\u32cc\u32cd\u32ce\u32cf\u32d0\u32d1\u32d2\u32d3\u32d4\u32d5\u32d6\u32d7\u32d8\u32d9\u32da\u32db\u32dc\u32dd\u32de\u32df\u32e0\u32e1\u32e2\u32e3\u32e4\u32e5\u32e6\u32e7\u32e8\u32e9\u32ea\u32eb\u32ec\u32ed\u32ee\u32ef\u32f0\u32f1\u32f2\u32f3\u32f4\u32f5\u32f6\u32f7\u32f8\u32f9\u32fa\u32fb\u32fc\u32fd\u32fe\u3300\u3301\u3302\u3303\u3304\u3305\u3306\u3307\u3308\u3309\u330a\u330b\u330c\u330d\u330e\u330f\u3310\u3311\u3312\u3313\u3314\u3315\u3316\u3317\u3318\u3319\u331a\u331b\u331c\u331d\u331e\u331f\u3320\u3321\u3322\u3323\u3324\u3325\u3326\u3327\u3328\u3329\u332a\u332b\u332c\u332d\u332e\u332f\u3330\u3331\u3332\u3333\u3334\u3335\u3336\u3337\u3338\u3339\u333a\u333b\u333c\u333d\u333e\u333f\u3340\u3341\u3342\u3343\u3344\u3345\u3346\u3347\u3348\u3349\u334a\u334b\u334c\u334d\u334e\u334f\u3350\u3351\u3352\u3353\u3354\u3355\u3356\u3357\u3358\u3359\u335a\u335b\u335c\u335d\u335e\u335f\u3360\u3361\u3362\u3363\u3364\u3365\u3366\u3367\u3368\u3369\u336a\u336b\u336c\u336d\u336e\u336f\u3370\u3371\u3372\u3373\u3374\u3375\u3376\u3377\u3378\u3379\u337a\u337b\u337c\u337d\u337e\u337f\u3380\u3381\u3382\u3383\u3384\u3385\u3386\u3387\u3388\u3389\u338a\u338b\u338c\u338d\u338e\u338f\u3390\u3391\u3392\u3393\u3394\u3395\u3396\u3397\u3398\u3399\u339a\u339b\u339c\u339d\u339e\u339f\u33a0\u33a1\u33a2\u33a3\u33a4\u33a5\u33a6\u33a7\u33a8\u33a9\u33aa\u33ab\u33ac\u33ad\u33ae\u33af\u33b0\u33b1\u33b2\u33b3\u33b4\u33b5\u33b6\u33b7\u33b8\u33b9\u33ba\u33bb\u33bc\u33bd\u33be\u33bf\u33c0\u33c1\u33c2\u33c3\u33c4\u33c5\u33c6\u33c7\u33c8\u33c9\u33ca\u33cb\u33cc\u33cd\u33ce\u33cf\u33d0\u33d1\u33d2\u33d3\u33d4\u33d5\u33d6\u33d7\u33d8\u33d9\u33da\u33db\u33dc\u33dd\u33de\u33df\u33e0\u33e1\u33e2\u33e3\u33e4\u33e5\u33e6\u33e7\u33e8\u33e9\u33ea\u33eb\u33ec\u33ed\u33ee\u33ef\u33f0\u33f1\u33f2\u33f3\u33f4\u33f5\u33f6\u33f7\u33f8\u33f9\u33fa\u33fb\u33fc\u33fd\u33fe\u33ff\u4dc0\u4dc1\u4dc2\u4dc3\u4dc4\u4dc5\u4dc6\u4dc7\u4dc8\u4dc9\u4dca\u4dcb\u4dcc\u4dcd\u4dce\u4dcf\u4dd0\u4dd1\u4dd2\u4dd3\u4dd4\u4dd5\u4dd6\u4dd7\u4dd8\u4dd9\u4dda\u4ddb\u4ddc\u4ddd\u4dde\u4ddf\u4de0\u4de1\u4de2\u4de3\u4de4\u4de5\u4de6\u4de7\u4de8\u4de9\u4dea\u4deb\u4dec\u4ded\u4dee\u4def\u4df0\u4df1\u4df2\u4df3\u4df4\u4df5\u4df6\u4df7\u4df8\u4df9\u4dfa\u4dfb\u4dfc\u4dfd\u4dfe\u4dff\ua490\ua491\ua492\ua493\ua494\ua495\ua496\ua497\ua498\ua499\ua49a\ua49b\ua49c\ua49d\ua49e\ua49f\ua4a0\ua4a1\ua4a2\ua4a3\ua4a4\ua4a5\ua4a6\ua4a7\ua4a8\ua4a9\ua4aa\ua4ab\ua4ac\ua4ad\ua4ae\ua4af\ua4b0\ua4b1\ua4b2\ua4b3\ua4b4\ua4b5\ua4b6\ua4b7\ua4b8\ua4b9\ua4ba\ua4bb\ua4bc\ua4bd\ua4be\ua4bf\ua4c0\ua4c1\ua4c2\ua4c3\ua4c4\ua4c5\ua4c6\ua828\ua829\ua82a\ua82b\ufdfd\uffe4\uffe8\uffed\uffee\ufffc\ufffd'
+
+Zl = u'\u2028'
+
+Zp = u'\u2029'
+
+Zs = u' \xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'
+
+cats = ['Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu', 'Mc', 'Me', 'Mn', 'Nd', 'Nl', 'No', 'Pc', 'Pd', 'Pe', 'Pf', 'Pi', 'Po', 'Ps', 'Sc', 'Sk', 'Sm', 'So', 'Zl', 'Zp', 'Zs']
+
+def combine(*args):
+ return u''.join([globals()[cat] for cat in args])
+
+xid_start = u'\u0041-\u005A\u005F\u0061-\u007A\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u01BA\u01BB\u01BC-\u01BF\u01C0-\u01C3\u01C4-\u0241\u0250-\u02AF\u02B0-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EE\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03CE\u03D0-\u03F5\u03F7-\u0481\u048A-\u04CE\u04D0-\u04F9\u0500-\u050F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0621-\u063A\u0640\u0641-\u064A\u066E-\u066F\u0671-\u06D3\u06D5\u06E5-\u06E6\u06EE-\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u076D\u0780-\u07A5\u07B1\u0904-\u0939\u093D\u0950\u0958-\u0961\u097D\u0985-\u098C\u098F-\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC-\u09DD\u09DF-\u09E1\u09F0-\u09F1\u0A05-\u0A0A\u0A0F-\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32-\u0A33\u0A35-\u0A36\u0A38-\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2-\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0-\u0AE1\u0B05-\u0B0C\u0B0F-\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32-\u0B33\u0B35-\u0B39\u0B3D\u0B5C-\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99-\u0B9A\u0B9C\u0B9E-\u0B9F\u0BA3-\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C60-\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0-\u0CE1\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D28\u0D2A-\u0D39\u0D60-\u0D61\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E40-\u0E45\u0E46\u0E81-\u0E82\u0E84\u0E87-\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA-\u0EAB\u0EAD-\u0EB0\u0EB2\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDD\u0F00\u0F40-\u0F47\u0F49-\u0F6A\u0F88-\u0F8B\u1000-\u1021\u1023-\u1027\u1029-\u102A\u1050-\u1055\u10A0-\u10C5\u10D0-\u10FA\u10FC\u1100-\u1159\u115F-\u11A2\u11A8-\u11F9\u1200-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u1676\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F0\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1842\u1843\u1844-\u1877\u1880-\u18A8\u1900-\u191C\u1950-\u196D\u1970-\u1974\u1980-\u19A9\u19C1-\u19C7\u1A00-\u1A16\u1D00-\u1D2B\u1D2C-\u1D61\u1D62-\u1D77\u1D78\u1D79-\u1D9A\u1D9B-\u1DBF\u1E00-\u1E9B\u1EA0-\u1EF9\u1F00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u2094\u2102\u2107\u210A-\u2113\u2115\u2118\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212E\u212F-\u2131\u2133-\u2134\u2135-\u2138\u2139\u213C-\u213F\u2145-\u2149\u2160-\u2183\u2C00-\u2C2E\u2C30-\u2C5E\u2C80-\u2CE4\u2D00-\u2D25\u2D30-\u2D65\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005\u3006\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303A\u303B\u303C\u3041-\u3096\u309D-\u309E\u309F\u30A1-\u30FA\u30FC-\u30FE\u30FF\u3105-\u312C\u3131-\u318E\u31A0-\u31B7\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FBB\uA000-\uA014\uA015\uA016-\uA48C\uA800-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uAC00-\uD7A3\uF900-\uFA2D\uFA30-\uFA6A\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40-\uFB41\uFB43-\uFB44\uFB46-\uFBB1\uFBD3-\uFC5D\uFC64-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDF9\uFE71\uFE73\uFE77\uFE79\uFE7B\uFE7D\uFE7F-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFF6F\uFF70\uFF71-\uFF9D\uFFA0-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC'
+
+xid_continue = u'\u0030-\u0039\u0041-\u005A\u005F\u0061-\u007A\u00AA\u00B5\u00B7\u00BA\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u01BA\u01BB\u01BC-\u01BF\u01C0-\u01C3\u01C4-\u0241\u0250-\u02AF\u02B0-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EE\u0300-\u036F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03CE\u03D0-\u03F5\u03F7-\u0481\u0483-\u0486\u048A-\u04CE\u04D0-\u04F9\u0500-\u050F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05B9\u05BB-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u0615\u0621-\u063A\u0640\u0641-\u064A\u064B-\u065E\u0660-\u0669\u066E-\u066F\u0670\u0671-\u06D3\u06D5\u06D6-\u06DC\u06DF-\u06E4\u06E5-\u06E6\u06E7-\u06E8\u06EA-\u06ED\u06EE-\u06EF\u06F0-\u06F9\u06FA-\u06FC\u06FF\u0710\u0711\u0712-\u072F\u0730-\u074A\u074D-\u076D\u0780-\u07A5\u07A6-\u07B0\u07B1\u0901-\u0902\u0903\u0904-\u0939\u093C\u093D\u093E-\u0940\u0941-\u0948\u0949-\u094C\u094D\u0950\u0951-\u0954\u0958-\u0961\u0962-\u0963\u0966-\u096F\u097D\u0981\u0982-\u0983\u0985-\u098C\u098F-\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC\u09BD\u09BE-\u09C0\u09C1-\u09C4\u09C7-\u09C8\u09CB-\u09CC\u09CD\u09CE\u09D7\u09DC-\u09DD\u09DF-\u09E1\u09E2-\u09E3\u09E6-\u09EF\u09F0-\u09F1\u0A01-\u0A02\u0A03\u0A05-\u0A0A\u0A0F-\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32-\u0A33\u0A35-\u0A36\u0A38-\u0A39\u0A3C\u0A3E-\u0A40\u0A41-\u0A42\u0A47-\u0A48\u0A4B-\u0A4D\u0A59-\u0A5C\u0A5E\u0A66-\u0A6F\u0A70-\u0A71\u0A72-\u0A74\u0A81-\u0A82\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2-\u0AB3\u0AB5-\u0AB9\u0ABC\u0ABD\u0ABE-\u0AC0\u0AC1-\u0AC5\u0AC7-\u0AC8\u0AC9\u0ACB-\u0ACC\u0ACD\u0AD0\u0AE0-\u0AE1\u0AE2-\u0AE3\u0AE6-\u0AEF\u0B01\u0B02-\u0B03\u0B05-\u0B0C\u0B0F-\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32-\u0B33\u0B35-\u0B39\u0B3C\u0B3D\u0B3E\u0B3F\u0B40\u0B41-\u0B43\u0B47-\u0B48\u0B4B-\u0B4C\u0B4D\u0B56\u0B57\u0B5C-\u0B5D\u0B5F-\u0B61\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99-\u0B9A\u0B9C\u0B9E-\u0B9F\u0BA3-\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BBF\u0BC0\u0BC1-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCC\u0BCD\u0BD7\u0BE6-\u0BEF\u0C01-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3E-\u0C40\u0C41-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55-\u0C56\u0C60-\u0C61\u0C66-\u0C6F\u0C82-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC\u0CBD\u0CBE\u0CBF\u0CC0-\u0CC4\u0CC6\u0CC7-\u0CC8\u0CCA-\u0CCB\u0CCC-\u0CCD\u0CD5-\u0CD6\u0CDE\u0CE0-\u0CE1\u0CE6-\u0CEF\u0D02-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D28\u0D2A-\u0D39\u0D3E-\u0D40\u0D41-\u0D43\u0D46-\u0D48\u0D4A-\u0D4C\u0D4D\u0D57\u0D60-\u0D61\u0D66-\u0D6F\u0D82-\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD1\u0DD2-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2-\u0DF3\u0E01-\u0E30\u0E31\u0E32-\u0E33\u0E34-\u0E3A\u0E40-\u0E45\u0E46\u0E47-\u0E4E\u0E50-\u0E59\u0E81-\u0E82\u0E84\u0E87-\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA-\u0EAB\u0EAD-\u0EB0\u0EB1\u0EB2-\u0EB3\u0EB4-\u0EB9\u0EBB-\u0EBC\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDD\u0F00\u0F18-\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F3F\u0F40-\u0F47\u0F49-\u0F6A\u0F71-\u0F7E\u0F7F\u0F80-\u0F84\u0F86-\u0F87\u0F88-\u0F8B\u0F90-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1021\u1023-\u1027\u1029-\u102A\u102C\u102D-\u1030\u1031\u1032\u1036-\u1037\u1038\u1039\u1040-\u1049\u1050-\u1055\u1056-\u1057\u1058-\u1059\u10A0-\u10C5\u10D0-\u10FA\u10FC\u1100-\u1159\u115F-\u11A2\u11A8-\u11F9\u1200-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u1676\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F0\u1700-\u170C\u170E-\u1711\u1712-\u1714\u1720-\u1731\u1732-\u1734\u1740-\u1751\u1752-\u1753\u1760-\u176C\u176E-\u1770\u1772-\u1773\u1780-\u17B3\u17B6\u17B7-\u17BD\u17BE-\u17C5\u17C6\u17C7-\u17C8\u17C9-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1842\u1843\u1844-\u1877\u1880-\u18A8\u18A9\u1900-\u191C\u1920-\u1922\u1923-\u1926\u1927-\u1928\u1929-\u192B\u1930-\u1931\u1932\u1933-\u1938\u1939-\u193B\u1946-\u194F\u1950-\u196D\u1970-\u1974\u1980-\u19A9\u19B0-\u19C0\u19C1-\u19C7\u19C8-\u19C9\u19D0-\u19D9\u1A00-\u1A16\u1A17-\u1A18\u1A19-\u1A1B\u1D00-\u1D2B\u1D2C-\u1D61\u1D62-\u1D77\u1D78\u1D79-\u1D9A\u1D9B-\u1DBF\u1DC0-\u1DC3\u1E00-\u1E9B\u1EA0-\u1EF9\u1F00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u203F-\u2040\u2054\u2071\u207F\u2090-\u2094\u20D0-\u20DC\u20E1\u20E5-\u20EB\u2102\u2107\u210A-\u2113\u2115\u2118\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212E\u212F-\u2131\u2133-\u2134\u2135-\u2138\u2139\u213C-\u213F\u2145-\u2149\u2160-\u2183\u2C00-\u2C2E\u2C30-\u2C5E\u2C80-\u2CE4\u2D00-\u2D25\u2D30-\u2D65\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005\u3006\u3007\u3021-\u3029\u302A-\u302F\u3031-\u3035\u3038-\u303A\u303B\u303C\u3041-\u3096\u3099-\u309A\u309D-\u309E\u309F\u30A1-\u30FA\u30FC-\u30FE\u30FF\u3105-\u312C\u3131-\u318E\u31A0-\u31B7\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FBB\uA000-\uA014\uA015\uA016-\uA48C\uA800-\uA801\uA802\uA803-\uA805\uA806\uA807-\uA80A\uA80B\uA80C-\uA822\uA823-\uA824\uA825-\uA826\uA827\uAC00-\uD7A3\uF900-\uFA2D\uFA30-\uFA6A\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1E\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40-\uFB41\uFB43-\uFB44\uFB46-\uFBB1\uFBD3-\uFC5D\uFC64-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDF9\uFE00-\uFE0F\uFE20-\uFE23\uFE33-\uFE34\uFE4D-\uFE4F\uFE71\uFE73\uFE77\uFE79\uFE7B\uFE7D\uFE7F-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFF6F\uFF70\uFF71-\uFF9D\uFF9E-\uFF9F\uFFA0-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC'
+
+def allexcept(*args):
+ newcats = cats[:]
+ for arg in args:
+ newcats.remove(arg)
+ return u''.join([globals()[cat] for cat in newcats])
+
+if __name__ == '__main__':
+ import unicodedata
+
+ categories = {}
+
+ f = open(__file__.rstrip('co'))
+ try:
+ content = f.read()
+ finally:
+ f.close()
+
+ header = content[:content.find('Cc =')]
+ footer = content[content.find("def combine("):]
+
+ for code in range(65535):
+ c = unichr(code)
+ cat = unicodedata.category(c)
+ categories.setdefault(cat, []).append(c)
+
+ f = open(__file__, 'w')
+ f.write(header)
+
+ for cat in sorted(categories):
+ val = u''.join(categories[cat])
+ if cat == 'Cs':
+ # Jython can't handle isolated surrogates
+ f.write("""\
+try:
+ Cs = eval(r"%r")
+except UnicodeDecodeError:
+ Cs = '' # Jython can't handle isolated surrogates\n\n""" % val)
+ else:
+ f.write('%s = %r\n\n' % (cat, val))
+ f.write('cats = %r\n\n' % sorted(categories.keys()))
+
+ f.write(footer)
+ f.close()
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/bccache.py b/deps/v8_inspector/deps/jinja2/jinja2/bccache.py
new file mode 100644
index 0000000000..f5bd3145f6
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/bccache.py
@@ -0,0 +1,362 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.bccache
+ ~~~~~~~~~~~~~~
+
+ This module implements the bytecode cache system Jinja is optionally
+ using. This is useful if you have very complex template situations and
+ the compiliation of all those templates slow down your application too
+ much.
+
+ Situations where this is useful are often forking web applications that
+ are initialized on the first request.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD.
+"""
+from os import path, listdir
+import os
+import sys
+import stat
+import errno
+import marshal
+import tempfile
+import fnmatch
+from hashlib import sha1
+from jinja2.utils import open_if_exists
+from jinja2._compat import BytesIO, pickle, PY2, text_type
+
+
+# marshal works better on 3.x, one hack less required
+if not PY2:
+ marshal_dump = marshal.dump
+ marshal_load = marshal.load
+else:
+
+ def marshal_dump(code, f):
+ if isinstance(f, file):
+ marshal.dump(code, f)
+ else:
+ f.write(marshal.dumps(code))
+
+ def marshal_load(f):
+ if isinstance(f, file):
+ return marshal.load(f)
+ return marshal.loads(f.read())
+
+
+bc_version = 2
+
+# magic version used to only change with new jinja versions. With 2.6
+# we change this to also take Python version changes into account. The
+# reason for this is that Python tends to segfault if fed earlier bytecode
+# versions because someone thought it would be a good idea to reuse opcodes
+# or make Python incompatible with earlier versions.
+bc_magic = 'j2'.encode('ascii') + \
+ pickle.dumps(bc_version, 2) + \
+ pickle.dumps((sys.version_info[0] << 24) | sys.version_info[1])
+
+
+class Bucket(object):
+ """Buckets are used to store the bytecode for one template. It's created
+ and initialized by the bytecode cache and passed to the loading functions.
+
+ The buckets get an internal checksum from the cache assigned and use this
+ to automatically reject outdated cache material. Individual bytecode
+ cache subclasses don't have to care about cache invalidation.
+ """
+
+ def __init__(self, environment, key, checksum):
+ self.environment = environment
+ self.key = key
+ self.checksum = checksum
+ self.reset()
+
+ def reset(self):
+ """Resets the bucket (unloads the bytecode)."""
+ self.code = None
+
+ def load_bytecode(self, f):
+ """Loads bytecode from a file or file like object."""
+ # make sure the magic header is correct
+ magic = f.read(len(bc_magic))
+ if magic != bc_magic:
+ self.reset()
+ return
+ # the source code of the file changed, we need to reload
+ checksum = pickle.load(f)
+ if self.checksum != checksum:
+ self.reset()
+ return
+ # if marshal_load fails then we need to reload
+ try:
+ self.code = marshal_load(f)
+ except (EOFError, ValueError, TypeError):
+ self.reset()
+ return
+
+ def write_bytecode(self, f):
+ """Dump the bytecode into the file or file like object passed."""
+ if self.code is None:
+ raise TypeError('can\'t write empty bucket')
+ f.write(bc_magic)
+ pickle.dump(self.checksum, f, 2)
+ marshal_dump(self.code, f)
+
+ def bytecode_from_string(self, string):
+ """Load bytecode from a string."""
+ self.load_bytecode(BytesIO(string))
+
+ def bytecode_to_string(self):
+ """Return the bytecode as string."""
+ out = BytesIO()
+ self.write_bytecode(out)
+ return out.getvalue()
+
+
+class BytecodeCache(object):
+ """To implement your own bytecode cache you have to subclass this class
+ and override :meth:`load_bytecode` and :meth:`dump_bytecode`. Both of
+ these methods are passed a :class:`~jinja2.bccache.Bucket`.
+
+ A very basic bytecode cache that saves the bytecode on the file system::
+
+ from os import path
+
+ class MyCache(BytecodeCache):
+
+ def __init__(self, directory):
+ self.directory = directory
+
+ def load_bytecode(self, bucket):
+ filename = path.join(self.directory, bucket.key)
+ if path.exists(filename):
+ with open(filename, 'rb') as f:
+ bucket.load_bytecode(f)
+
+ def dump_bytecode(self, bucket):
+ filename = path.join(self.directory, bucket.key)
+ with open(filename, 'wb') as f:
+ bucket.write_bytecode(f)
+
+ A more advanced version of a filesystem based bytecode cache is part of
+ Jinja2.
+ """
+
+ def load_bytecode(self, bucket):
+ """Subclasses have to override this method to load bytecode into a
+ bucket. If they are not able to find code in the cache for the
+ bucket, it must not do anything.
+ """
+ raise NotImplementedError()
+
+ def dump_bytecode(self, bucket):
+ """Subclasses have to override this method to write the bytecode
+ from a bucket back to the cache. If it unable to do so it must not
+ fail silently but raise an exception.
+ """
+ raise NotImplementedError()
+
+ def clear(self):
+ """Clears the cache. This method is not used by Jinja2 but should be
+ implemented to allow applications to clear the bytecode cache used
+ by a particular environment.
+ """
+
+ def get_cache_key(self, name, filename=None):
+ """Returns the unique hash key for this template name."""
+ hash = sha1(name.encode('utf-8'))
+ if filename is not None:
+ filename = '|' + filename
+ if isinstance(filename, text_type):
+ filename = filename.encode('utf-8')
+ hash.update(filename)
+ return hash.hexdigest()
+
+ def get_source_checksum(self, source):
+ """Returns a checksum for the source."""
+ return sha1(source.encode('utf-8')).hexdigest()
+
+ def get_bucket(self, environment, name, filename, source):
+ """Return a cache bucket for the given template. All arguments are
+ mandatory but filename may be `None`.
+ """
+ key = self.get_cache_key(name, filename)
+ checksum = self.get_source_checksum(source)
+ bucket = Bucket(environment, key, checksum)
+ self.load_bytecode(bucket)
+ return bucket
+
+ def set_bucket(self, bucket):
+ """Put the bucket into the cache."""
+ self.dump_bytecode(bucket)
+
+
+class FileSystemBytecodeCache(BytecodeCache):
+ """A bytecode cache that stores bytecode on the filesystem. It accepts
+ two arguments: The directory where the cache items are stored and a
+ pattern string that is used to build the filename.
+
+ If no directory is specified a default cache directory is selected. On
+ Windows the user's temp directory is used, on UNIX systems a directory
+ is created for the user in the system temp directory.
+
+ The pattern can be used to have multiple separate caches operate on the
+ same directory. The default pattern is ``'__jinja2_%s.cache'``. ``%s``
+ is replaced with the cache key.
+
+ >>> bcc = FileSystemBytecodeCache('/tmp/jinja_cache', '%s.cache')
+
+ This bytecode cache supports clearing of the cache using the clear method.
+ """
+
+ def __init__(self, directory=None, pattern='__jinja2_%s.cache'):
+ if directory is None:
+ directory = self._get_default_cache_dir()
+ self.directory = directory
+ self.pattern = pattern
+
+ def _get_default_cache_dir(self):
+ def _unsafe_dir():
+ raise RuntimeError('Cannot determine safe temp directory. You '
+ 'need to explicitly provide one.')
+
+ tmpdir = tempfile.gettempdir()
+
+ # On windows the temporary directory is used specific unless
+ # explicitly forced otherwise. We can just use that.
+ if os.name == 'nt':
+ return tmpdir
+ if not hasattr(os, 'getuid'):
+ _unsafe_dir()
+
+ dirname = '_jinja2-cache-%d' % os.getuid()
+ actual_dir = os.path.join(tmpdir, dirname)
+
+ try:
+ os.mkdir(actual_dir, stat.S_IRWXU)
+ except OSError as e:
+ if e.errno != errno.EEXIST:
+ raise
+ try:
+ os.chmod(actual_dir, stat.S_IRWXU)
+ actual_dir_stat = os.lstat(actual_dir)
+ if actual_dir_stat.st_uid != os.getuid() \
+ or not stat.S_ISDIR(actual_dir_stat.st_mode) \
+ or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU:
+ _unsafe_dir()
+ except OSError as e:
+ if e.errno != errno.EEXIST:
+ raise
+
+ actual_dir_stat = os.lstat(actual_dir)
+ if actual_dir_stat.st_uid != os.getuid() \
+ or not stat.S_ISDIR(actual_dir_stat.st_mode) \
+ or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU:
+ _unsafe_dir()
+
+ return actual_dir
+
+ def _get_cache_filename(self, bucket):
+ return path.join(self.directory, self.pattern % bucket.key)
+
+ def load_bytecode(self, bucket):
+ f = open_if_exists(self._get_cache_filename(bucket), 'rb')
+ if f is not None:
+ try:
+ bucket.load_bytecode(f)
+ finally:
+ f.close()
+
+ def dump_bytecode(self, bucket):
+ f = open(self._get_cache_filename(bucket), 'wb')
+ try:
+ bucket.write_bytecode(f)
+ finally:
+ f.close()
+
+ def clear(self):
+ # imported lazily here because google app-engine doesn't support
+ # write access on the file system and the function does not exist
+ # normally.
+ from os import remove
+ files = fnmatch.filter(listdir(self.directory), self.pattern % '*')
+ for filename in files:
+ try:
+ remove(path.join(self.directory, filename))
+ except OSError:
+ pass
+
+
+class MemcachedBytecodeCache(BytecodeCache):
+ """This class implements a bytecode cache that uses a memcache cache for
+ storing the information. It does not enforce a specific memcache library
+ (tummy's memcache or cmemcache) but will accept any class that provides
+ the minimal interface required.
+
+ Libraries compatible with this class:
+
+ - `werkzeug <http://werkzeug.pocoo.org/>`_.contrib.cache
+ - `python-memcached <http://www.tummy.com/Community/software/python-memcached/>`_
+ - `cmemcache <http://gijsbert.org/cmemcache/>`_
+
+ (Unfortunately the django cache interface is not compatible because it
+ does not support storing binary data, only unicode. You can however pass
+ the underlying cache client to the bytecode cache which is available
+ as `django.core.cache.cache._client`.)
+
+ The minimal interface for the client passed to the constructor is this:
+
+ .. class:: MinimalClientInterface
+
+ .. method:: set(key, value[, timeout])
+
+ Stores the bytecode in the cache. `value` is a string and
+ `timeout` the timeout of the key. If timeout is not provided
+ a default timeout or no timeout should be assumed, if it's
+ provided it's an integer with the number of seconds the cache
+ item should exist.
+
+ .. method:: get(key)
+
+ Returns the value for the cache key. If the item does not
+ exist in the cache the return value must be `None`.
+
+ The other arguments to the constructor are the prefix for all keys that
+ is added before the actual cache key and the timeout for the bytecode in
+ the cache system. We recommend a high (or no) timeout.
+
+ This bytecode cache does not support clearing of used items in the cache.
+ The clear method is a no-operation function.
+
+ .. versionadded:: 2.7
+ Added support for ignoring memcache errors through the
+ `ignore_memcache_errors` parameter.
+ """
+
+ def __init__(self, client, prefix='jinja2/bytecode/', timeout=None,
+ ignore_memcache_errors=True):
+ self.client = client
+ self.prefix = prefix
+ self.timeout = timeout
+ self.ignore_memcache_errors = ignore_memcache_errors
+
+ def load_bytecode(self, bucket):
+ try:
+ code = self.client.get(self.prefix + bucket.key)
+ except Exception:
+ if not self.ignore_memcache_errors:
+ raise
+ code = None
+ if code is not None:
+ bucket.bytecode_from_string(code)
+
+ def dump_bytecode(self, bucket):
+ args = (self.prefix + bucket.key, bucket.bytecode_to_string())
+ if self.timeout is not None:
+ args += (self.timeout,)
+ try:
+ self.client.set(*args)
+ except Exception:
+ if not self.ignore_memcache_errors:
+ raise
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/compiler.py b/deps/v8_inspector/deps/jinja2/jinja2/compiler.py
new file mode 100644
index 0000000000..fad007b596
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/compiler.py
@@ -0,0 +1,1686 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.compiler
+ ~~~~~~~~~~~~~~~
+
+ Compiles nodes into python code.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+from itertools import chain
+from copy import deepcopy
+from keyword import iskeyword as is_python_keyword
+from jinja2 import nodes
+from jinja2.nodes import EvalContext
+from jinja2.visitor import NodeVisitor
+from jinja2.exceptions import TemplateAssertionError
+from jinja2.utils import Markup, concat, escape
+from jinja2._compat import range_type, text_type, string_types, \
+ iteritems, NativeStringIO, imap
+
+
+operators = {
+ 'eq': '==',
+ 'ne': '!=',
+ 'gt': '>',
+ 'gteq': '>=',
+ 'lt': '<',
+ 'lteq': '<=',
+ 'in': 'in',
+ 'notin': 'not in'
+}
+
+# what method to iterate over items do we want to use for dict iteration
+# in generated code? on 2.x let's go with iteritems, on 3.x with items
+if hasattr(dict, 'iteritems'):
+ dict_item_iter = 'iteritems'
+else:
+ dict_item_iter = 'items'
+
+
+# does if 0: dummy(x) get us x into the scope?
+def unoptimize_before_dead_code():
+ x = 42
+ def f():
+ if 0: dummy(x)
+ return f
+
+# The getattr is necessary for pypy which does not set this attribute if
+# no closure is on the function
+unoptimize_before_dead_code = bool(
+ getattr(unoptimize_before_dead_code(), '__closure__', None))
+
+
+def generate(node, environment, name, filename, stream=None,
+ defer_init=False):
+ """Generate the python source for a node tree."""
+ if not isinstance(node, nodes.Template):
+ raise TypeError('Can\'t compile non template nodes')
+ generator = environment.code_generator_class(environment, name, filename,
+ stream, defer_init)
+ generator.visit(node)
+ if stream is None:
+ return generator.stream.getvalue()
+
+
+def has_safe_repr(value):
+ """Does the node have a safe representation?"""
+ if value is None or value is NotImplemented or value is Ellipsis:
+ return True
+ if isinstance(value, (bool, int, float, complex, range_type,
+ Markup) + string_types):
+ return True
+ if isinstance(value, (tuple, list, set, frozenset)):
+ for item in value:
+ if not has_safe_repr(item):
+ return False
+ return True
+ elif isinstance(value, dict):
+ for key, value in iteritems(value):
+ if not has_safe_repr(key):
+ return False
+ if not has_safe_repr(value):
+ return False
+ return True
+ return False
+
+
+def find_undeclared(nodes, names):
+ """Check if the names passed are accessed undeclared. The return value
+ is a set of all the undeclared names from the sequence of names found.
+ """
+ visitor = UndeclaredNameVisitor(names)
+ try:
+ for node in nodes:
+ visitor.visit(node)
+ except VisitorExit:
+ pass
+ return visitor.undeclared
+
+
+class Identifiers(object):
+ """Tracks the status of identifiers in frames."""
+
+ def __init__(self):
+ # variables that are known to be declared (probably from outer
+ # frames or because they are special for the frame)
+ self.declared = set()
+
+ # undeclared variables from outer scopes
+ self.outer_undeclared = set()
+
+ # names that are accessed without being explicitly declared by
+ # this one or any of the outer scopes. Names can appear both in
+ # declared and undeclared.
+ self.undeclared = set()
+
+ # names that are declared locally
+ self.declared_locally = set()
+
+ # names that are declared by parameters
+ self.declared_parameter = set()
+
+ def add_special(self, name):
+ """Register a special name like `loop`."""
+ self.undeclared.discard(name)
+ self.declared.add(name)
+
+ def is_declared(self, name):
+ """Check if a name is declared in this or an outer scope."""
+ if name in self.declared_locally or name in self.declared_parameter:
+ return True
+ return name in self.declared
+
+ def copy(self):
+ return deepcopy(self)
+
+
+class Frame(object):
+ """Holds compile time information for us."""
+
+ def __init__(self, eval_ctx, parent=None):
+ self.eval_ctx = eval_ctx
+ self.identifiers = Identifiers()
+
+ # a toplevel frame is the root + soft frames such as if conditions.
+ self.toplevel = False
+
+ # the root frame is basically just the outermost frame, so no if
+ # conditions. This information is used to optimize inheritance
+ # situations.
+ self.rootlevel = False
+
+ # in some dynamic inheritance situations the compiler needs to add
+ # write tests around output statements.
+ self.require_output_check = parent and parent.require_output_check
+
+ # inside some tags we are using a buffer rather than yield statements.
+ # this for example affects {% filter %} or {% macro %}. If a frame
+ # is buffered this variable points to the name of the list used as
+ # buffer.
+ self.buffer = None
+
+ # the name of the block we're in, otherwise None.
+ self.block = parent and parent.block or None
+
+ # a set of actually assigned names
+ self.assigned_names = set()
+
+ # the parent of this frame
+ self.parent = parent
+
+ if parent is not None:
+ self.identifiers.declared.update(
+ parent.identifiers.declared |
+ parent.identifiers.declared_parameter |
+ parent.assigned_names
+ )
+ self.identifiers.outer_undeclared.update(
+ parent.identifiers.undeclared -
+ self.identifiers.declared
+ )
+ self.buffer = parent.buffer
+
+ def copy(self):
+ """Create a copy of the current one."""
+ rv = object.__new__(self.__class__)
+ rv.__dict__.update(self.__dict__)
+ rv.identifiers = object.__new__(self.identifiers.__class__)
+ rv.identifiers.__dict__.update(self.identifiers.__dict__)
+ return rv
+
+ def inspect(self, nodes):
+ """Walk the node and check for identifiers. If the scope is hard (eg:
+ enforce on a python level) overrides from outer scopes are tracked
+ differently.
+ """
+ visitor = FrameIdentifierVisitor(self.identifiers)
+ for node in nodes:
+ visitor.visit(node)
+
+ def find_shadowed(self, extra=()):
+ """Find all the shadowed names. extra is an iterable of variables
+ that may be defined with `add_special` which may occour scoped.
+ """
+ i = self.identifiers
+ return (i.declared | i.outer_undeclared) & \
+ (i.declared_locally | i.declared_parameter) | \
+ set(x for x in extra if i.is_declared(x))
+
+ def inner(self):
+ """Return an inner frame."""
+ return Frame(self.eval_ctx, self)
+
+ def soft(self):
+ """Return a soft frame. A soft frame may not be modified as
+ standalone thing as it shares the resources with the frame it
+ was created of, but it's not a rootlevel frame any longer.
+ """
+ rv = self.copy()
+ rv.rootlevel = False
+ return rv
+
+ __copy__ = copy
+
+
+class VisitorExit(RuntimeError):
+ """Exception used by the `UndeclaredNameVisitor` to signal a stop."""
+
+
+class DependencyFinderVisitor(NodeVisitor):
+ """A visitor that collects filter and test calls."""
+
+ def __init__(self):
+ self.filters = set()
+ self.tests = set()
+
+ def visit_Filter(self, node):
+ self.generic_visit(node)
+ self.filters.add(node.name)
+
+ def visit_Test(self, node):
+ self.generic_visit(node)
+ self.tests.add(node.name)
+
+ def visit_Block(self, node):
+ """Stop visiting at blocks."""
+
+
+class UndeclaredNameVisitor(NodeVisitor):
+ """A visitor that checks if a name is accessed without being
+ declared. This is different from the frame visitor as it will
+ not stop at closure frames.
+ """
+
+ def __init__(self, names):
+ self.names = set(names)
+ self.undeclared = set()
+
+ def visit_Name(self, node):
+ if node.ctx == 'load' and node.name in self.names:
+ self.undeclared.add(node.name)
+ if self.undeclared == self.names:
+ raise VisitorExit()
+ else:
+ self.names.discard(node.name)
+
+ def visit_Block(self, node):
+ """Stop visiting a blocks."""
+
+
+class FrameIdentifierVisitor(NodeVisitor):
+ """A visitor for `Frame.inspect`."""
+
+ def __init__(self, identifiers):
+ self.identifiers = identifiers
+
+ def visit_Name(self, node):
+ """All assignments to names go through this function."""
+ if node.ctx == 'store':
+ self.identifiers.declared_locally.add(node.name)
+ elif node.ctx == 'param':
+ self.identifiers.declared_parameter.add(node.name)
+ elif node.ctx == 'load' and not \
+ self.identifiers.is_declared(node.name):
+ self.identifiers.undeclared.add(node.name)
+
+ def visit_If(self, node):
+ self.visit(node.test)
+ real_identifiers = self.identifiers
+
+ old_names = real_identifiers.declared_locally | \
+ real_identifiers.declared_parameter
+
+ def inner_visit(nodes):
+ if not nodes:
+ return set()
+ self.identifiers = real_identifiers.copy()
+ for subnode in nodes:
+ self.visit(subnode)
+ rv = self.identifiers.declared_locally - old_names
+ # we have to remember the undeclared variables of this branch
+ # because we will have to pull them.
+ real_identifiers.undeclared.update(self.identifiers.undeclared)
+ self.identifiers = real_identifiers
+ return rv
+
+ body = inner_visit(node.body)
+ else_ = inner_visit(node.else_ or ())
+
+ # the differences between the two branches are also pulled as
+ # undeclared variables
+ real_identifiers.undeclared.update(body.symmetric_difference(else_) -
+ real_identifiers.declared)
+
+ # remember those that are declared.
+ real_identifiers.declared_locally.update(body | else_)
+
+ def visit_Macro(self, node):
+ self.identifiers.declared_locally.add(node.name)
+
+ def visit_Import(self, node):
+ self.generic_visit(node)
+ self.identifiers.declared_locally.add(node.target)
+
+ def visit_FromImport(self, node):
+ self.generic_visit(node)
+ for name in node.names:
+ if isinstance(name, tuple):
+ self.identifiers.declared_locally.add(name[1])
+ else:
+ self.identifiers.declared_locally.add(name)
+
+ def visit_Assign(self, node):
+ """Visit assignments in the correct order."""
+ self.visit(node.node)
+ self.visit(node.target)
+
+ def visit_For(self, node):
+ """Visiting stops at for blocks. However the block sequence
+ is visited as part of the outer scope.
+ """
+ self.visit(node.iter)
+
+ def visit_CallBlock(self, node):
+ self.visit(node.call)
+
+ def visit_FilterBlock(self, node):
+ self.visit(node.filter)
+
+ def visit_AssignBlock(self, node):
+ """Stop visiting at block assigns."""
+
+ def visit_Scope(self, node):
+ """Stop visiting at scopes."""
+
+ def visit_Block(self, node):
+ """Stop visiting at blocks."""
+
+
+class CompilerExit(Exception):
+ """Raised if the compiler encountered a situation where it just
+ doesn't make sense to further process the code. Any block that
+ raises such an exception is not further processed.
+ """
+
+
+class CodeGenerator(NodeVisitor):
+
+ def __init__(self, environment, name, filename, stream=None,
+ defer_init=False):
+ if stream is None:
+ stream = NativeStringIO()
+ self.environment = environment
+ self.name = name
+ self.filename = filename
+ self.stream = stream
+ self.created_block_context = False
+ self.defer_init = defer_init
+
+ # aliases for imports
+ self.import_aliases = {}
+
+ # a registry for all blocks. Because blocks are moved out
+ # into the global python scope they are registered here
+ self.blocks = {}
+
+ # the number of extends statements so far
+ self.extends_so_far = 0
+
+ # some templates have a rootlevel extends. In this case we
+ # can safely assume that we're a child template and do some
+ # more optimizations.
+ self.has_known_extends = False
+
+ # the current line number
+ self.code_lineno = 1
+
+ # registry of all filters and tests (global, not block local)
+ self.tests = {}
+ self.filters = {}
+
+ # the debug information
+ self.debug_info = []
+ self._write_debug_info = None
+
+ # the number of new lines before the next write()
+ self._new_lines = 0
+
+ # the line number of the last written statement
+ self._last_line = 0
+
+ # true if nothing was written so far.
+ self._first_write = True
+
+ # used by the `temporary_identifier` method to get new
+ # unique, temporary identifier
+ self._last_identifier = 0
+
+ # the current indentation
+ self._indentation = 0
+
+ # -- Various compilation helpers
+
+ def fail(self, msg, lineno):
+ """Fail with a :exc:`TemplateAssertionError`."""
+ raise TemplateAssertionError(msg, lineno, self.name, self.filename)
+
+ def temporary_identifier(self):
+ """Get a new unique identifier."""
+ self._last_identifier += 1
+ return 't_%d' % self._last_identifier
+
+ def buffer(self, frame):
+ """Enable buffering for the frame from that point onwards."""
+ frame.buffer = self.temporary_identifier()
+ self.writeline('%s = []' % frame.buffer)
+
+ def return_buffer_contents(self, frame):
+ """Return the buffer contents of the frame."""
+ if frame.eval_ctx.volatile:
+ self.writeline('if context.eval_ctx.autoescape:')
+ self.indent()
+ self.writeline('return Markup(concat(%s))' % frame.buffer)
+ self.outdent()
+ self.writeline('else:')
+ self.indent()
+ self.writeline('return concat(%s)' % frame.buffer)
+ self.outdent()
+ elif frame.eval_ctx.autoescape:
+ self.writeline('return Markup(concat(%s))' % frame.buffer)
+ else:
+ self.writeline('return concat(%s)' % frame.buffer)
+
+ def indent(self):
+ """Indent by one."""
+ self._indentation += 1
+
+ def outdent(self, step=1):
+ """Outdent by step."""
+ self._indentation -= step
+
+ def start_write(self, frame, node=None):
+ """Yield or write into the frame buffer."""
+ if frame.buffer is None:
+ self.writeline('yield ', node)
+ else:
+ self.writeline('%s.append(' % frame.buffer, node)
+
+ def end_write(self, frame):
+ """End the writing process started by `start_write`."""
+ if frame.buffer is not None:
+ self.write(')')
+
+ def simple_write(self, s, frame, node=None):
+ """Simple shortcut for start_write + write + end_write."""
+ self.start_write(frame, node)
+ self.write(s)
+ self.end_write(frame)
+
+ def blockvisit(self, nodes, frame):
+ """Visit a list of nodes as block in a frame. If the current frame
+ is no buffer a dummy ``if 0: yield None`` is written automatically
+ unless the force_generator parameter is set to False.
+ """
+ if frame.buffer is None:
+ self.writeline('if 0: yield None')
+ else:
+ self.writeline('pass')
+ try:
+ for node in nodes:
+ self.visit(node, frame)
+ except CompilerExit:
+ pass
+
+ def write(self, x):
+ """Write a string into the output stream."""
+ if self._new_lines:
+ if not self._first_write:
+ self.stream.write('\n' * self._new_lines)
+ self.code_lineno += self._new_lines
+ if self._write_debug_info is not None:
+ self.debug_info.append((self._write_debug_info,
+ self.code_lineno))
+ self._write_debug_info = None
+ self._first_write = False
+ self.stream.write(' ' * self._indentation)
+ self._new_lines = 0
+ self.stream.write(x)
+
+ def writeline(self, x, node=None, extra=0):
+ """Combination of newline and write."""
+ self.newline(node, extra)
+ self.write(x)
+
+ def newline(self, node=None, extra=0):
+ """Add one or more newlines before the next write."""
+ self._new_lines = max(self._new_lines, 1 + extra)
+ if node is not None and node.lineno != self._last_line:
+ self._write_debug_info = node.lineno
+ self._last_line = node.lineno
+
+ def signature(self, node, frame, extra_kwargs=None):
+ """Writes a function call to the stream for the current node.
+ A leading comma is added automatically. The extra keyword
+ arguments may not include python keywords otherwise a syntax
+ error could occour. The extra keyword arguments should be given
+ as python dict.
+ """
+ # if any of the given keyword arguments is a python keyword
+ # we have to make sure that no invalid call is created.
+ kwarg_workaround = False
+ for kwarg in chain((x.key for x in node.kwargs), extra_kwargs or ()):
+ if is_python_keyword(kwarg):
+ kwarg_workaround = True
+ break
+
+ for arg in node.args:
+ self.write(', ')
+ self.visit(arg, frame)
+
+ if not kwarg_workaround:
+ for kwarg in node.kwargs:
+ self.write(', ')
+ self.visit(kwarg, frame)
+ if extra_kwargs is not None:
+ for key, value in iteritems(extra_kwargs):
+ self.write(', %s=%s' % (key, value))
+ if node.dyn_args:
+ self.write(', *')
+ self.visit(node.dyn_args, frame)
+
+ if kwarg_workaround:
+ if node.dyn_kwargs is not None:
+ self.write(', **dict({')
+ else:
+ self.write(', **{')
+ for kwarg in node.kwargs:
+ self.write('%r: ' % kwarg.key)
+ self.visit(kwarg.value, frame)
+ self.write(', ')
+ if extra_kwargs is not None:
+ for key, value in iteritems(extra_kwargs):
+ self.write('%r: %s, ' % (key, value))
+ if node.dyn_kwargs is not None:
+ self.write('}, **')
+ self.visit(node.dyn_kwargs, frame)
+ self.write(')')
+ else:
+ self.write('}')
+
+ elif node.dyn_kwargs is not None:
+ self.write(', **')
+ self.visit(node.dyn_kwargs, frame)
+
+ def pull_locals(self, frame):
+ """Pull all the references identifiers into the local scope."""
+ for name in frame.identifiers.undeclared:
+ self.writeline('l_%s = context.resolve(%r)' % (name, name))
+
+ def pull_dependencies(self, nodes):
+ """Pull all the dependencies."""
+ visitor = DependencyFinderVisitor()
+ for node in nodes:
+ visitor.visit(node)
+ for dependency in 'filters', 'tests':
+ mapping = getattr(self, dependency)
+ for name in getattr(visitor, dependency):
+ if name not in mapping:
+ mapping[name] = self.temporary_identifier()
+ self.writeline('%s = environment.%s[%r]' %
+ (mapping[name], dependency, name))
+
+ def unoptimize_scope(self, frame):
+ """Disable Python optimizations for the frame."""
+ # XXX: this is not that nice but it has no real overhead. It
+ # mainly works because python finds the locals before dead code
+ # is removed. If that breaks we have to add a dummy function
+ # that just accepts the arguments and does nothing.
+ if frame.identifiers.declared:
+ self.writeline('%sdummy(%s)' % (
+ unoptimize_before_dead_code and 'if 0: ' or '',
+ ', '.join('l_' + name for name in frame.identifiers.declared)
+ ))
+
+ def push_scope(self, frame, extra_vars=()):
+ """This function returns all the shadowed variables in a dict
+ in the form name: alias and will write the required assignments
+ into the current scope. No indentation takes place.
+
+ This also predefines locally declared variables from the loop
+ body because under some circumstances it may be the case that
+
+ `extra_vars` is passed to `Frame.find_shadowed`.
+ """
+ aliases = {}
+ for name in frame.find_shadowed(extra_vars):
+ aliases[name] = ident = self.temporary_identifier()
+ self.writeline('%s = l_%s' % (ident, name))
+ to_declare = set()
+ for name in frame.identifiers.declared_locally:
+ if name not in aliases:
+ to_declare.add('l_' + name)
+ if to_declare:
+ self.writeline(' = '.join(to_declare) + ' = missing')
+ return aliases
+
+ def pop_scope(self, aliases, frame):
+ """Restore all aliases and delete unused variables."""
+ for name, alias in iteritems(aliases):
+ self.writeline('l_%s = %s' % (name, alias))
+ to_delete = set()
+ for name in frame.identifiers.declared_locally:
+ if name not in aliases:
+ to_delete.add('l_' + name)
+ if to_delete:
+ # we cannot use the del statement here because enclosed
+ # scopes can trigger a SyntaxError:
+ # a = 42; b = lambda: a; del a
+ self.writeline(' = '.join(to_delete) + ' = missing')
+
+ def function_scoping(self, node, frame, children=None,
+ find_special=True):
+ """In Jinja a few statements require the help of anonymous
+ functions. Those are currently macros and call blocks and in
+ the future also recursive loops. As there is currently
+ technical limitation that doesn't allow reading and writing a
+ variable in a scope where the initial value is coming from an
+ outer scope, this function tries to fall back with a common
+ error message. Additionally the frame passed is modified so
+ that the argumetns are collected and callers are looked up.
+
+ This will return the modified frame.
+ """
+ # we have to iterate twice over it, make sure that works
+ if children is None:
+ children = node.iter_child_nodes()
+ children = list(children)
+ func_frame = frame.inner()
+ func_frame.inspect(children)
+
+ # variables that are undeclared (accessed before declaration) and
+ # declared locally *and* part of an outside scope raise a template
+ # assertion error. Reason: we can't generate reasonable code from
+ # it without aliasing all the variables.
+ # this could be fixed in Python 3 where we have the nonlocal
+ # keyword or if we switch to bytecode generation
+ overridden_closure_vars = (
+ func_frame.identifiers.undeclared &
+ func_frame.identifiers.declared &
+ (func_frame.identifiers.declared_locally |
+ func_frame.identifiers.declared_parameter)
+ )
+ if overridden_closure_vars:
+ self.fail('It\'s not possible to set and access variables '
+ 'derived from an outer scope! (affects: %s)' %
+ ', '.join(sorted(overridden_closure_vars)), node.lineno)
+
+ # remove variables from a closure from the frame's undeclared
+ # identifiers.
+ func_frame.identifiers.undeclared -= (
+ func_frame.identifiers.undeclared &
+ func_frame.identifiers.declared
+ )
+
+ # no special variables for this scope, abort early
+ if not find_special:
+ return func_frame
+
+ func_frame.accesses_kwargs = False
+ func_frame.accesses_varargs = False
+ func_frame.accesses_caller = False
+ func_frame.arguments = args = ['l_' + x.name for x in node.args]
+
+ undeclared = find_undeclared(children, ('caller', 'kwargs', 'varargs'))
+
+ if 'caller' in undeclared:
+ func_frame.accesses_caller = True
+ func_frame.identifiers.add_special('caller')
+ args.append('l_caller')
+ if 'kwargs' in undeclared:
+ func_frame.accesses_kwargs = True
+ func_frame.identifiers.add_special('kwargs')
+ args.append('l_kwargs')
+ if 'varargs' in undeclared:
+ func_frame.accesses_varargs = True
+ func_frame.identifiers.add_special('varargs')
+ args.append('l_varargs')
+ return func_frame
+
+ def macro_body(self, node, frame, children=None):
+ """Dump the function def of a macro or call block."""
+ frame = self.function_scoping(node, frame, children)
+ # macros are delayed, they never require output checks
+ frame.require_output_check = False
+ args = frame.arguments
+ # XXX: this is an ugly fix for the loop nesting bug
+ # (tests.test_old_bugs.test_loop_call_bug). This works around
+ # a identifier nesting problem we have in general. It's just more
+ # likely to happen in loops which is why we work around it. The
+ # real solution would be "nonlocal" all the identifiers that are
+ # leaking into a new python frame and might be used both unassigned
+ # and assigned.
+ if 'loop' in frame.identifiers.declared:
+ args = args + ['l_loop=l_loop']
+ self.writeline('def macro(%s):' % ', '.join(args), node)
+ self.indent()
+ self.buffer(frame)
+ self.pull_locals(frame)
+ self.blockvisit(node.body, frame)
+ self.return_buffer_contents(frame)
+ self.outdent()
+ return frame
+
+ def macro_def(self, node, frame):
+ """Dump the macro definition for the def created by macro_body."""
+ arg_tuple = ', '.join(repr(x.name) for x in node.args)
+ name = getattr(node, 'name', None)
+ if len(node.args) == 1:
+ arg_tuple += ','
+ self.write('Macro(environment, macro, %r, (%s), (' %
+ (name, arg_tuple))
+ for arg in node.defaults:
+ self.visit(arg, frame)
+ self.write(', ')
+ self.write('), %r, %r, %r)' % (
+ bool(frame.accesses_kwargs),
+ bool(frame.accesses_varargs),
+ bool(frame.accesses_caller)
+ ))
+
+ def position(self, node):
+ """Return a human readable position for the node."""
+ rv = 'line %d' % node.lineno
+ if self.name is not None:
+ rv += ' in ' + repr(self.name)
+ return rv
+
+ # -- Statement Visitors
+
+ def visit_Template(self, node, frame=None):
+ assert frame is None, 'no root frame allowed'
+ eval_ctx = EvalContext(self.environment, self.name)
+
+ from jinja2.runtime import __all__ as exported
+ self.writeline('from __future__ import division')
+ self.writeline('from jinja2.runtime import ' + ', '.join(exported))
+ if not unoptimize_before_dead_code:
+ self.writeline('dummy = lambda *x: None')
+
+ # if we want a deferred initialization we cannot move the
+ # environment into a local name
+ envenv = not self.defer_init and ', environment=environment' or ''
+
+ # do we have an extends tag at all? If not, we can save some
+ # overhead by just not processing any inheritance code.
+ have_extends = node.find(nodes.Extends) is not None
+
+ # find all blocks
+ for block in node.find_all(nodes.Block):
+ if block.name in self.blocks:
+ self.fail('block %r defined twice' % block.name, block.lineno)
+ self.blocks[block.name] = block
+
+ # find all imports and import them
+ for import_ in node.find_all(nodes.ImportedName):
+ if import_.importname not in self.import_aliases:
+ imp = import_.importname
+ self.import_aliases[imp] = alias = self.temporary_identifier()
+ if '.' in imp:
+ module, obj = imp.rsplit('.', 1)
+ self.writeline('from %s import %s as %s' %
+ (module, obj, alias))
+ else:
+ self.writeline('import %s as %s' % (imp, alias))
+
+ # add the load name
+ self.writeline('name = %r' % self.name)
+
+ # generate the root render function.
+ self.writeline('def root(context%s):' % envenv, extra=1)
+
+ # process the root
+ frame = Frame(eval_ctx)
+ frame.inspect(node.body)
+ frame.toplevel = frame.rootlevel = True
+ frame.require_output_check = have_extends and not self.has_known_extends
+ self.indent()
+ if have_extends:
+ self.writeline('parent_template = None')
+ if 'self' in find_undeclared(node.body, ('self',)):
+ frame.identifiers.add_special('self')
+ self.writeline('l_self = TemplateReference(context)')
+ self.pull_locals(frame)
+ self.pull_dependencies(node.body)
+ self.blockvisit(node.body, frame)
+ self.outdent()
+
+ # make sure that the parent root is called.
+ if have_extends:
+ if not self.has_known_extends:
+ self.indent()
+ self.writeline('if parent_template is not None:')
+ self.indent()
+ self.writeline('for event in parent_template.'
+ 'root_render_func(context):')
+ self.indent()
+ self.writeline('yield event')
+ self.outdent(2 + (not self.has_known_extends))
+
+ # at this point we now have the blocks collected and can visit them too.
+ for name, block in iteritems(self.blocks):
+ block_frame = Frame(eval_ctx)
+ block_frame.inspect(block.body)
+ block_frame.block = name
+ self.writeline('def block_%s(context%s):' % (name, envenv),
+ block, 1)
+ self.indent()
+ undeclared = find_undeclared(block.body, ('self', 'super'))
+ if 'self' in undeclared:
+ block_frame.identifiers.add_special('self')
+ self.writeline('l_self = TemplateReference(context)')
+ if 'super' in undeclared:
+ block_frame.identifiers.add_special('super')
+ self.writeline('l_super = context.super(%r, '
+ 'block_%s)' % (name, name))
+ self.pull_locals(block_frame)
+ self.pull_dependencies(block.body)
+ self.blockvisit(block.body, block_frame)
+ self.outdent()
+
+ self.writeline('blocks = {%s}' % ', '.join('%r: block_%s' % (x, x)
+ for x in self.blocks),
+ extra=1)
+
+ # add a function that returns the debug info
+ self.writeline('debug_info = %r' % '&'.join('%s=%s' % x for x
+ in self.debug_info))
+
+ def visit_Block(self, node, frame):
+ """Call a block and register it for the template."""
+ level = 1
+ if frame.toplevel:
+ # if we know that we are a child template, there is no need to
+ # check if we are one
+ if self.has_known_extends:
+ return
+ if self.extends_so_far > 0:
+ self.writeline('if parent_template is None:')
+ self.indent()
+ level += 1
+ context = node.scoped and 'context.derived(locals())' or 'context'
+ self.writeline('for event in context.blocks[%r][0](%s):' % (
+ node.name, context), node)
+ self.indent()
+ self.simple_write('event', frame)
+ self.outdent(level)
+
+ def visit_Extends(self, node, frame):
+ """Calls the extender."""
+ if not frame.toplevel:
+ self.fail('cannot use extend from a non top-level scope',
+ node.lineno)
+
+ # if the number of extends statements in general is zero so
+ # far, we don't have to add a check if something extended
+ # the template before this one.
+ if self.extends_so_far > 0:
+
+ # if we have a known extends we just add a template runtime
+ # error into the generated code. We could catch that at compile
+ # time too, but i welcome it not to confuse users by throwing the
+ # same error at different times just "because we can".
+ if not self.has_known_extends:
+ self.writeline('if parent_template is not None:')
+ self.indent()
+ self.writeline('raise TemplateRuntimeError(%r)' %
+ 'extended multiple times')
+
+ # if we have a known extends already we don't need that code here
+ # as we know that the template execution will end here.
+ if self.has_known_extends:
+ raise CompilerExit()
+ else:
+ self.outdent()
+
+ self.writeline('parent_template = environment.get_template(', node)
+ self.visit(node.template, frame)
+ self.write(', %r)' % self.name)
+ self.writeline('for name, parent_block in parent_template.'
+ 'blocks.%s():' % dict_item_iter)
+ self.indent()
+ self.writeline('context.blocks.setdefault(name, []).'
+ 'append(parent_block)')
+ self.outdent()
+
+ # if this extends statement was in the root level we can take
+ # advantage of that information and simplify the generated code
+ # in the top level from this point onwards
+ if frame.rootlevel:
+ self.has_known_extends = True
+
+ # and now we have one more
+ self.extends_so_far += 1
+
+ def visit_Include(self, node, frame):
+ """Handles includes."""
+ if node.with_context:
+ self.unoptimize_scope(frame)
+ if node.ignore_missing:
+ self.writeline('try:')
+ self.indent()
+
+ func_name = 'get_or_select_template'
+ if isinstance(node.template, nodes.Const):
+ if isinstance(node.template.value, string_types):
+ func_name = 'get_template'
+ elif isinstance(node.template.value, (tuple, list)):
+ func_name = 'select_template'
+ elif isinstance(node.template, (nodes.Tuple, nodes.List)):
+ func_name = 'select_template'
+
+ self.writeline('template = environment.%s(' % func_name, node)
+ self.visit(node.template, frame)
+ self.write(', %r)' % self.name)
+ if node.ignore_missing:
+ self.outdent()
+ self.writeline('except TemplateNotFound:')
+ self.indent()
+ self.writeline('pass')
+ self.outdent()
+ self.writeline('else:')
+ self.indent()
+
+ if node.with_context:
+ self.writeline('for event in template.root_render_func('
+ 'template.new_context(context.parent, True, '
+ 'locals())):')
+ else:
+ self.writeline('for event in template.module._body_stream:')
+
+ self.indent()
+ self.simple_write('event', frame)
+ self.outdent()
+
+ if node.ignore_missing:
+ self.outdent()
+
+ def visit_Import(self, node, frame):
+ """Visit regular imports."""
+ if node.with_context:
+ self.unoptimize_scope(frame)
+ self.writeline('l_%s = ' % node.target, node)
+ if frame.toplevel:
+ self.write('context.vars[%r] = ' % node.target)
+ self.write('environment.get_template(')
+ self.visit(node.template, frame)
+ self.write(', %r).' % self.name)
+ if node.with_context:
+ self.write('make_module(context.parent, True, locals())')
+ else:
+ self.write('module')
+ if frame.toplevel and not node.target.startswith('_'):
+ self.writeline('context.exported_vars.discard(%r)' % node.target)
+ frame.assigned_names.add(node.target)
+
+ def visit_FromImport(self, node, frame):
+ """Visit named imports."""
+ self.newline(node)
+ self.write('included_template = environment.get_template(')
+ self.visit(node.template, frame)
+ self.write(', %r).' % self.name)
+ if node.with_context:
+ self.write('make_module(context.parent, True)')
+ else:
+ self.write('module')
+
+ var_names = []
+ discarded_names = []
+ for name in node.names:
+ if isinstance(name, tuple):
+ name, alias = name
+ else:
+ alias = name
+ self.writeline('l_%s = getattr(included_template, '
+ '%r, missing)' % (alias, name))
+ self.writeline('if l_%s is missing:' % alias)
+ self.indent()
+ self.writeline('l_%s = environment.undefined(%r %% '
+ 'included_template.__name__, '
+ 'name=%r)' %
+ (alias, 'the template %%r (imported on %s) does '
+ 'not export the requested name %s' % (
+ self.position(node),
+ repr(name)
+ ), name))
+ self.outdent()
+ if frame.toplevel:
+ var_names.append(alias)
+ if not alias.startswith('_'):
+ discarded_names.append(alias)
+ frame.assigned_names.add(alias)
+
+ if var_names:
+ if len(var_names) == 1:
+ name = var_names[0]
+ self.writeline('context.vars[%r] = l_%s' % (name, name))
+ else:
+ self.writeline('context.vars.update({%s})' % ', '.join(
+ '%r: l_%s' % (name, name) for name in var_names
+ ))
+ if discarded_names:
+ if len(discarded_names) == 1:
+ self.writeline('context.exported_vars.discard(%r)' %
+ discarded_names[0])
+ else:
+ self.writeline('context.exported_vars.difference_'
+ 'update((%s))' % ', '.join(imap(repr, discarded_names)))
+
+ def visit_For(self, node, frame):
+ # when calculating the nodes for the inner frame we have to exclude
+ # the iterator contents from it
+ children = node.iter_child_nodes(exclude=('iter',))
+ if node.recursive:
+ loop_frame = self.function_scoping(node, frame, children,
+ find_special=False)
+ else:
+ loop_frame = frame.inner()
+ loop_frame.inspect(children)
+
+ # try to figure out if we have an extended loop. An extended loop
+ # is necessary if the loop is in recursive mode if the special loop
+ # variable is accessed in the body.
+ extended_loop = node.recursive or 'loop' in \
+ find_undeclared(node.iter_child_nodes(
+ only=('body',)), ('loop',))
+
+ # if we don't have an recursive loop we have to find the shadowed
+ # variables at that point. Because loops can be nested but the loop
+ # variable is a special one we have to enforce aliasing for it.
+ if not node.recursive:
+ aliases = self.push_scope(loop_frame, ('loop',))
+
+ # otherwise we set up a buffer and add a function def
+ else:
+ self.writeline('def loop(reciter, loop_render_func, depth=0):', node)
+ self.indent()
+ self.buffer(loop_frame)
+ aliases = {}
+
+ # make sure the loop variable is a special one and raise a template
+ # assertion error if a loop tries to write to loop
+ if extended_loop:
+ self.writeline('l_loop = missing')
+ loop_frame.identifiers.add_special('loop')
+ for name in node.find_all(nodes.Name):
+ if name.ctx == 'store' and name.name == 'loop':
+ self.fail('Can\'t assign to special loop variable '
+ 'in for-loop target', name.lineno)
+
+ self.pull_locals(loop_frame)
+ if node.else_:
+ iteration_indicator = self.temporary_identifier()
+ self.writeline('%s = 1' % iteration_indicator)
+
+ # Create a fake parent loop if the else or test section of a
+ # loop is accessing the special loop variable and no parent loop
+ # exists.
+ if 'loop' not in aliases and 'loop' in find_undeclared(
+ node.iter_child_nodes(only=('else_', 'test')), ('loop',)):
+ self.writeline("l_loop = environment.undefined(%r, name='loop')" %
+ ("'loop' is undefined. the filter section of a loop as well "
+ "as the else block don't have access to the special 'loop'"
+ " variable of the current loop. Because there is no parent "
+ "loop it's undefined. Happened in loop on %s" %
+ self.position(node)))
+
+ self.writeline('for ', node)
+ self.visit(node.target, loop_frame)
+ self.write(extended_loop and ', l_loop in LoopContext(' or ' in ')
+
+ # if we have an extened loop and a node test, we filter in the
+ # "outer frame".
+ if extended_loop and node.test is not None:
+ self.write('(')
+ self.visit(node.target, loop_frame)
+ self.write(' for ')
+ self.visit(node.target, loop_frame)
+ self.write(' in ')
+ if node.recursive:
+ self.write('reciter')
+ else:
+ self.visit(node.iter, loop_frame)
+ self.write(' if (')
+ test_frame = loop_frame.copy()
+ self.visit(node.test, test_frame)
+ self.write('))')
+
+ elif node.recursive:
+ self.write('reciter')
+ else:
+ self.visit(node.iter, loop_frame)
+
+ if node.recursive:
+ self.write(', loop_render_func, depth):')
+ else:
+ self.write(extended_loop and '):' or ':')
+
+ # tests in not extended loops become a continue
+ if not extended_loop and node.test is not None:
+ self.indent()
+ self.writeline('if not ')
+ self.visit(node.test, loop_frame)
+ self.write(':')
+ self.indent()
+ self.writeline('continue')
+ self.outdent(2)
+
+ self.indent()
+ self.blockvisit(node.body, loop_frame)
+ if node.else_:
+ self.writeline('%s = 0' % iteration_indicator)
+ self.outdent()
+
+ if node.else_:
+ self.writeline('if %s:' % iteration_indicator)
+ self.indent()
+ self.blockvisit(node.else_, loop_frame)
+ self.outdent()
+
+ # reset the aliases if there are any.
+ if not node.recursive:
+ self.pop_scope(aliases, loop_frame)
+
+ # if the node was recursive we have to return the buffer contents
+ # and start the iteration code
+ if node.recursive:
+ self.return_buffer_contents(loop_frame)
+ self.outdent()
+ self.start_write(frame, node)
+ self.write('loop(')
+ self.visit(node.iter, frame)
+ self.write(', loop)')
+ self.end_write(frame)
+
+ def visit_If(self, node, frame):
+ if_frame = frame.soft()
+ self.writeline('if ', node)
+ self.visit(node.test, if_frame)
+ self.write(':')
+ self.indent()
+ self.blockvisit(node.body, if_frame)
+ self.outdent()
+ if node.else_:
+ self.writeline('else:')
+ self.indent()
+ self.blockvisit(node.else_, if_frame)
+ self.outdent()
+
+ def visit_Macro(self, node, frame):
+ macro_frame = self.macro_body(node, frame)
+ self.newline()
+ if frame.toplevel:
+ if not node.name.startswith('_'):
+ self.write('context.exported_vars.add(%r)' % node.name)
+ self.writeline('context.vars[%r] = ' % node.name)
+ self.write('l_%s = ' % node.name)
+ self.macro_def(node, macro_frame)
+ frame.assigned_names.add(node.name)
+
+ def visit_CallBlock(self, node, frame):
+ children = node.iter_child_nodes(exclude=('call',))
+ call_frame = self.macro_body(node, frame, children)
+ self.writeline('caller = ')
+ self.macro_def(node, call_frame)
+ self.start_write(frame, node)
+ self.visit_Call(node.call, call_frame, forward_caller=True)
+ self.end_write(frame)
+
+ def visit_FilterBlock(self, node, frame):
+ filter_frame = frame.inner()
+ filter_frame.inspect(node.iter_child_nodes())
+ aliases = self.push_scope(filter_frame)
+ self.pull_locals(filter_frame)
+ self.buffer(filter_frame)
+ self.blockvisit(node.body, filter_frame)
+ self.start_write(frame, node)
+ self.visit_Filter(node.filter, filter_frame)
+ self.end_write(frame)
+ self.pop_scope(aliases, filter_frame)
+
+ def visit_ExprStmt(self, node, frame):
+ self.newline(node)
+ self.visit(node.node, frame)
+
+ def visit_Output(self, node, frame):
+ # if we have a known extends statement, we don't output anything
+ # if we are in a require_output_check section
+ if self.has_known_extends and frame.require_output_check:
+ return
+
+ allow_constant_finalize = True
+ if self.environment.finalize:
+ func = self.environment.finalize
+ if getattr(func, 'contextfunction', False) or \
+ getattr(func, 'evalcontextfunction', False):
+ allow_constant_finalize = False
+ elif getattr(func, 'environmentfunction', False):
+ finalize = lambda x: text_type(
+ self.environment.finalize(self.environment, x))
+ else:
+ finalize = lambda x: text_type(self.environment.finalize(x))
+ else:
+ finalize = text_type
+
+ # if we are inside a frame that requires output checking, we do so
+ outdent_later = False
+ if frame.require_output_check:
+ self.writeline('if parent_template is None:')
+ self.indent()
+ outdent_later = True
+
+ # try to evaluate as many chunks as possible into a static
+ # string at compile time.
+ body = []
+ for child in node.nodes:
+ try:
+ if not allow_constant_finalize:
+ raise nodes.Impossible()
+ const = child.as_const(frame.eval_ctx)
+ except nodes.Impossible:
+ body.append(child)
+ continue
+ # the frame can't be volatile here, becaus otherwise the
+ # as_const() function would raise an Impossible exception
+ # at that point.
+ try:
+ if frame.eval_ctx.autoescape:
+ if hasattr(const, '__html__'):
+ const = const.__html__()
+ else:
+ const = escape(const)
+ const = finalize(const)
+ except Exception:
+ # if something goes wrong here we evaluate the node
+ # at runtime for easier debugging
+ body.append(child)
+ continue
+ if body and isinstance(body[-1], list):
+ body[-1].append(const)
+ else:
+ body.append([const])
+
+ # if we have less than 3 nodes or a buffer we yield or extend/append
+ if len(body) < 3 or frame.buffer is not None:
+ if frame.buffer is not None:
+ # for one item we append, for more we extend
+ if len(body) == 1:
+ self.writeline('%s.append(' % frame.buffer)
+ else:
+ self.writeline('%s.extend((' % frame.buffer)
+ self.indent()
+ for item in body:
+ if isinstance(item, list):
+ val = repr(concat(item))
+ if frame.buffer is None:
+ self.writeline('yield ' + val)
+ else:
+ self.writeline(val + ', ')
+ else:
+ if frame.buffer is None:
+ self.writeline('yield ', item)
+ else:
+ self.newline(item)
+ close = 1
+ if frame.eval_ctx.volatile:
+ self.write('(context.eval_ctx.autoescape and'
+ ' escape or to_string)(')
+ elif frame.eval_ctx.autoescape:
+ self.write('escape(')
+ else:
+ self.write('to_string(')
+ if self.environment.finalize is not None:
+ self.write('environment.finalize(')
+ if getattr(self.environment.finalize,
+ "contextfunction", False):
+ self.write('context, ')
+ close += 1
+ self.visit(item, frame)
+ self.write(')' * close)
+ if frame.buffer is not None:
+ self.write(', ')
+ if frame.buffer is not None:
+ # close the open parentheses
+ self.outdent()
+ self.writeline(len(body) == 1 and ')' or '))')
+
+ # otherwise we create a format string as this is faster in that case
+ else:
+ format = []
+ arguments = []
+ for item in body:
+ if isinstance(item, list):
+ format.append(concat(item).replace('%', '%%'))
+ else:
+ format.append('%s')
+ arguments.append(item)
+ self.writeline('yield ')
+ self.write(repr(concat(format)) + ' % (')
+ self.indent()
+ for argument in arguments:
+ self.newline(argument)
+ close = 0
+ if frame.eval_ctx.volatile:
+ self.write('(context.eval_ctx.autoescape and'
+ ' escape or to_string)(')
+ close += 1
+ elif frame.eval_ctx.autoescape:
+ self.write('escape(')
+ close += 1
+ if self.environment.finalize is not None:
+ self.write('environment.finalize(')
+ if getattr(self.environment.finalize,
+ 'contextfunction', False):
+ self.write('context, ')
+ elif getattr(self.environment.finalize,
+ 'evalcontextfunction', False):
+ self.write('context.eval_ctx, ')
+ elif getattr(self.environment.finalize,
+ 'environmentfunction', False):
+ self.write('environment, ')
+ close += 1
+ self.visit(argument, frame)
+ self.write(')' * close + ', ')
+ self.outdent()
+ self.writeline(')')
+
+ if outdent_later:
+ self.outdent()
+
+ def make_assignment_frame(self, frame):
+ # toplevel assignments however go into the local namespace and
+ # the current template's context. We create a copy of the frame
+ # here and add a set so that the Name visitor can add the assigned
+ # names here.
+ if not frame.toplevel:
+ return frame
+ assignment_frame = frame.copy()
+ assignment_frame.toplevel_assignments = set()
+ return assignment_frame
+
+ def export_assigned_vars(self, frame, assignment_frame):
+ if not frame.toplevel:
+ return
+ public_names = [x for x in assignment_frame.toplevel_assignments
+ if not x.startswith('_')]
+ if len(assignment_frame.toplevel_assignments) == 1:
+ name = next(iter(assignment_frame.toplevel_assignments))
+ self.writeline('context.vars[%r] = l_%s' % (name, name))
+ else:
+ self.writeline('context.vars.update({')
+ for idx, name in enumerate(assignment_frame.toplevel_assignments):
+ if idx:
+ self.write(', ')
+ self.write('%r: l_%s' % (name, name))
+ self.write('})')
+ if public_names:
+ if len(public_names) == 1:
+ self.writeline('context.exported_vars.add(%r)' %
+ public_names[0])
+ else:
+ self.writeline('context.exported_vars.update((%s))' %
+ ', '.join(imap(repr, public_names)))
+
+ def visit_Assign(self, node, frame):
+ self.newline(node)
+ assignment_frame = self.make_assignment_frame(frame)
+ self.visit(node.target, assignment_frame)
+ self.write(' = ')
+ self.visit(node.node, frame)
+ self.export_assigned_vars(frame, assignment_frame)
+
+ def visit_AssignBlock(self, node, frame):
+ block_frame = frame.inner()
+ block_frame.inspect(node.body)
+ aliases = self.push_scope(block_frame)
+ self.pull_locals(block_frame)
+ self.buffer(block_frame)
+ self.blockvisit(node.body, block_frame)
+ self.pop_scope(aliases, block_frame)
+
+ assignment_frame = self.make_assignment_frame(frame)
+ self.newline(node)
+ self.visit(node.target, assignment_frame)
+ self.write(' = concat(%s)' % block_frame.buffer)
+ self.export_assigned_vars(frame, assignment_frame)
+
+ # -- Expression Visitors
+
+ def visit_Name(self, node, frame):
+ if node.ctx == 'store' and frame.toplevel:
+ frame.toplevel_assignments.add(node.name)
+ self.write('l_' + node.name)
+ frame.assigned_names.add(node.name)
+
+ def visit_Const(self, node, frame):
+ val = node.value
+ if isinstance(val, float):
+ self.write(str(val))
+ else:
+ self.write(repr(val))
+
+ def visit_TemplateData(self, node, frame):
+ try:
+ self.write(repr(node.as_const(frame.eval_ctx)))
+ except nodes.Impossible:
+ self.write('(context.eval_ctx.autoescape and Markup or identity)(%r)'
+ % node.data)
+
+ def visit_Tuple(self, node, frame):
+ self.write('(')
+ idx = -1
+ for idx, item in enumerate(node.items):
+ if idx:
+ self.write(', ')
+ self.visit(item, frame)
+ self.write(idx == 0 and ',)' or ')')
+
+ def visit_List(self, node, frame):
+ self.write('[')
+ for idx, item in enumerate(node.items):
+ if idx:
+ self.write(', ')
+ self.visit(item, frame)
+ self.write(']')
+
+ def visit_Dict(self, node, frame):
+ self.write('{')
+ for idx, item in enumerate(node.items):
+ if idx:
+ self.write(', ')
+ self.visit(item.key, frame)
+ self.write(': ')
+ self.visit(item.value, frame)
+ self.write('}')
+
+ def binop(operator, interceptable=True):
+ def visitor(self, node, frame):
+ if self.environment.sandboxed and \
+ operator in self.environment.intercepted_binops:
+ self.write('environment.call_binop(context, %r, ' % operator)
+ self.visit(node.left, frame)
+ self.write(', ')
+ self.visit(node.right, frame)
+ else:
+ self.write('(')
+ self.visit(node.left, frame)
+ self.write(' %s ' % operator)
+ self.visit(node.right, frame)
+ self.write(')')
+ return visitor
+
+ def uaop(operator, interceptable=True):
+ def visitor(self, node, frame):
+ if self.environment.sandboxed and \
+ operator in self.environment.intercepted_unops:
+ self.write('environment.call_unop(context, %r, ' % operator)
+ self.visit(node.node, frame)
+ else:
+ self.write('(' + operator)
+ self.visit(node.node, frame)
+ self.write(')')
+ return visitor
+
+ visit_Add = binop('+')
+ visit_Sub = binop('-')
+ visit_Mul = binop('*')
+ visit_Div = binop('/')
+ visit_FloorDiv = binop('//')
+ visit_Pow = binop('**')
+ visit_Mod = binop('%')
+ visit_And = binop('and', interceptable=False)
+ visit_Or = binop('or', interceptable=False)
+ visit_Pos = uaop('+')
+ visit_Neg = uaop('-')
+ visit_Not = uaop('not ', interceptable=False)
+ del binop, uaop
+
+ def visit_Concat(self, node, frame):
+ if frame.eval_ctx.volatile:
+ func_name = '(context.eval_ctx.volatile and' \
+ ' markup_join or unicode_join)'
+ elif frame.eval_ctx.autoescape:
+ func_name = 'markup_join'
+ else:
+ func_name = 'unicode_join'
+ self.write('%s((' % func_name)
+ for arg in node.nodes:
+ self.visit(arg, frame)
+ self.write(', ')
+ self.write('))')
+
+ def visit_Compare(self, node, frame):
+ self.visit(node.expr, frame)
+ for op in node.ops:
+ self.visit(op, frame)
+
+ def visit_Operand(self, node, frame):
+ self.write(' %s ' % operators[node.op])
+ self.visit(node.expr, frame)
+
+ def visit_Getattr(self, node, frame):
+ self.write('environment.getattr(')
+ self.visit(node.node, frame)
+ self.write(', %r)' % node.attr)
+
+ def visit_Getitem(self, node, frame):
+ # slices bypass the environment getitem method.
+ if isinstance(node.arg, nodes.Slice):
+ self.visit(node.node, frame)
+ self.write('[')
+ self.visit(node.arg, frame)
+ self.write(']')
+ else:
+ self.write('environment.getitem(')
+ self.visit(node.node, frame)
+ self.write(', ')
+ self.visit(node.arg, frame)
+ self.write(')')
+
+ def visit_Slice(self, node, frame):
+ if node.start is not None:
+ self.visit(node.start, frame)
+ self.write(':')
+ if node.stop is not None:
+ self.visit(node.stop, frame)
+ if node.step is not None:
+ self.write(':')
+ self.visit(node.step, frame)
+
+ def visit_Filter(self, node, frame):
+ self.write(self.filters[node.name] + '(')
+ func = self.environment.filters.get(node.name)
+ if func is None:
+ self.fail('no filter named %r' % node.name, node.lineno)
+ if getattr(func, 'contextfilter', False):
+ self.write('context, ')
+ elif getattr(func, 'evalcontextfilter', False):
+ self.write('context.eval_ctx, ')
+ elif getattr(func, 'environmentfilter', False):
+ self.write('environment, ')
+
+ # if the filter node is None we are inside a filter block
+ # and want to write to the current buffer
+ if node.node is not None:
+ self.visit(node.node, frame)
+ elif frame.eval_ctx.volatile:
+ self.write('(context.eval_ctx.autoescape and'
+ ' Markup(concat(%s)) or concat(%s))' %
+ (frame.buffer, frame.buffer))
+ elif frame.eval_ctx.autoescape:
+ self.write('Markup(concat(%s))' % frame.buffer)
+ else:
+ self.write('concat(%s)' % frame.buffer)
+ self.signature(node, frame)
+ self.write(')')
+
+ def visit_Test(self, node, frame):
+ self.write(self.tests[node.name] + '(')
+ if node.name not in self.environment.tests:
+ self.fail('no test named %r' % node.name, node.lineno)
+ self.visit(node.node, frame)
+ self.signature(node, frame)
+ self.write(')')
+
+ def visit_CondExpr(self, node, frame):
+ def write_expr2():
+ if node.expr2 is not None:
+ return self.visit(node.expr2, frame)
+ self.write('environment.undefined(%r)' % ('the inline if-'
+ 'expression on %s evaluated to false and '
+ 'no else section was defined.' % self.position(node)))
+
+ self.write('(')
+ self.visit(node.expr1, frame)
+ self.write(' if ')
+ self.visit(node.test, frame)
+ self.write(' else ')
+ write_expr2()
+ self.write(')')
+
+ def visit_Call(self, node, frame, forward_caller=False):
+ if self.environment.sandboxed:
+ self.write('environment.call(context, ')
+ else:
+ self.write('context.call(')
+ self.visit(node.node, frame)
+ extra_kwargs = forward_caller and {'caller': 'caller'} or None
+ self.signature(node, frame, extra_kwargs)
+ self.write(')')
+
+ def visit_Keyword(self, node, frame):
+ self.write(node.key + '=')
+ self.visit(node.value, frame)
+
+ # -- Unused nodes for extensions
+
+ def visit_MarkSafe(self, node, frame):
+ self.write('Markup(')
+ self.visit(node.expr, frame)
+ self.write(')')
+
+ def visit_MarkSafeIfAutoescape(self, node, frame):
+ self.write('(context.eval_ctx.autoescape and Markup or identity)(')
+ self.visit(node.expr, frame)
+ self.write(')')
+
+ def visit_EnvironmentAttribute(self, node, frame):
+ self.write('environment.' + node.name)
+
+ def visit_ExtensionAttribute(self, node, frame):
+ self.write('environment.extensions[%r].%s' % (node.identifier, node.name))
+
+ def visit_ImportedName(self, node, frame):
+ self.write(self.import_aliases[node.importname])
+
+ def visit_InternalName(self, node, frame):
+ self.write(node.name)
+
+ def visit_ContextReference(self, node, frame):
+ self.write('context')
+
+ def visit_Continue(self, node, frame):
+ self.writeline('continue', node)
+
+ def visit_Break(self, node, frame):
+ self.writeline('break', node)
+
+ def visit_Scope(self, node, frame):
+ scope_frame = frame.inner()
+ scope_frame.inspect(node.iter_child_nodes())
+ aliases = self.push_scope(scope_frame)
+ self.pull_locals(scope_frame)
+ self.blockvisit(node.body, scope_frame)
+ self.pop_scope(aliases, scope_frame)
+
+ def visit_EvalContextModifier(self, node, frame):
+ for keyword in node.options:
+ self.writeline('context.eval_ctx.%s = ' % keyword.key)
+ self.visit(keyword.value, frame)
+ try:
+ val = keyword.value.as_const(frame.eval_ctx)
+ except nodes.Impossible:
+ frame.eval_ctx.volatile = True
+ else:
+ setattr(frame.eval_ctx, keyword.key, val)
+
+ def visit_ScopedEvalContextModifier(self, node, frame):
+ old_ctx_name = self.temporary_identifier()
+ safed_ctx = frame.eval_ctx.save()
+ self.writeline('%s = context.eval_ctx.save()' % old_ctx_name)
+ self.visit_EvalContextModifier(node, frame)
+ for child in node.body:
+ self.visit(child, frame)
+ frame.eval_ctx.revert(safed_ctx)
+ self.writeline('context.eval_ctx.revert(%s)' % old_ctx_name)
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/constants.py b/deps/v8_inspector/deps/jinja2/jinja2/constants.py
new file mode 100644
index 0000000000..cab203cc77
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/constants.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja.constants
+ ~~~~~~~~~~~~~~~
+
+ Various constants.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+
+
+#: list of lorem ipsum words used by the lipsum() helper function
+LOREM_IPSUM_WORDS = u'''\
+a ac accumsan ad adipiscing aenean aliquam aliquet amet ante aptent arcu at
+auctor augue bibendum blandit class commodo condimentum congue consectetuer
+consequat conubia convallis cras cubilia cum curabitur curae cursus dapibus
+diam dictum dictumst dignissim dis dolor donec dui duis egestas eget eleifend
+elementum elit enim erat eros est et etiam eu euismod facilisi facilisis fames
+faucibus felis fermentum feugiat fringilla fusce gravida habitant habitasse hac
+hendrerit hymenaeos iaculis id imperdiet in inceptos integer interdum ipsum
+justo lacinia lacus laoreet lectus leo libero ligula litora lobortis lorem
+luctus maecenas magna magnis malesuada massa mattis mauris metus mi molestie
+mollis montes morbi mus nam nascetur natoque nec neque netus nibh nisi nisl non
+nonummy nostra nulla nullam nunc odio orci ornare parturient pede pellentesque
+penatibus per pharetra phasellus placerat platea porta porttitor posuere
+potenti praesent pretium primis proin pulvinar purus quam quis quisque rhoncus
+ridiculus risus rutrum sagittis sapien scelerisque sed sem semper senectus sit
+sociis sociosqu sodales sollicitudin suscipit suspendisse taciti tellus tempor
+tempus tincidunt torquent tortor tristique turpis ullamcorper ultrices
+ultricies urna ut varius vehicula vel velit venenatis vestibulum vitae vivamus
+viverra volutpat vulputate'''
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/debug.py b/deps/v8_inspector/deps/jinja2/jinja2/debug.py
new file mode 100644
index 0000000000..3252748369
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/debug.py
@@ -0,0 +1,350 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.debug
+ ~~~~~~~~~~~~
+
+ Implements the debug interface for Jinja. This module does some pretty
+ ugly stuff with the Python traceback system in order to achieve tracebacks
+ with correct line numbers, locals and contents.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import sys
+import traceback
+from types import TracebackType, CodeType
+from jinja2.utils import missing, internal_code
+from jinja2.exceptions import TemplateSyntaxError
+from jinja2._compat import iteritems, reraise, PY2
+
+# on pypy we can take advantage of transparent proxies
+try:
+ from __pypy__ import tproxy
+except ImportError:
+ tproxy = None
+
+
+# how does the raise helper look like?
+try:
+ exec("raise TypeError, 'foo'")
+except SyntaxError:
+ raise_helper = 'raise __jinja_exception__[1]'
+except TypeError:
+ raise_helper = 'raise __jinja_exception__[0], __jinja_exception__[1]'
+
+
+class TracebackFrameProxy(object):
+ """Proxies a traceback frame."""
+
+ def __init__(self, tb):
+ self.tb = tb
+ self._tb_next = None
+
+ @property
+ def tb_next(self):
+ return self._tb_next
+
+ def set_next(self, next):
+ if tb_set_next is not None:
+ try:
+ tb_set_next(self.tb, next and next.tb or None)
+ except Exception:
+ # this function can fail due to all the hackery it does
+ # on various python implementations. We just catch errors
+ # down and ignore them if necessary.
+ pass
+ self._tb_next = next
+
+ @property
+ def is_jinja_frame(self):
+ return '__jinja_template__' in self.tb.tb_frame.f_globals
+
+ def __getattr__(self, name):
+ return getattr(self.tb, name)
+
+
+def make_frame_proxy(frame):
+ proxy = TracebackFrameProxy(frame)
+ if tproxy is None:
+ return proxy
+ def operation_handler(operation, *args, **kwargs):
+ if operation in ('__getattribute__', '__getattr__'):
+ return getattr(proxy, args[0])
+ elif operation == '__setattr__':
+ proxy.__setattr__(*args, **kwargs)
+ else:
+ return getattr(proxy, operation)(*args, **kwargs)
+ return tproxy(TracebackType, operation_handler)
+
+
+class ProcessedTraceback(object):
+ """Holds a Jinja preprocessed traceback for printing or reraising."""
+
+ def __init__(self, exc_type, exc_value, frames):
+ assert frames, 'no frames for this traceback?'
+ self.exc_type = exc_type
+ self.exc_value = exc_value
+ self.frames = frames
+
+ # newly concatenate the frames (which are proxies)
+ prev_tb = None
+ for tb in self.frames:
+ if prev_tb is not None:
+ prev_tb.set_next(tb)
+ prev_tb = tb
+ prev_tb.set_next(None)
+
+ def render_as_text(self, limit=None):
+ """Return a string with the traceback."""
+ lines = traceback.format_exception(self.exc_type, self.exc_value,
+ self.frames[0], limit=limit)
+ return ''.join(lines).rstrip()
+
+ def render_as_html(self, full=False):
+ """Return a unicode string with the traceback as rendered HTML."""
+ from jinja2.debugrenderer import render_traceback
+ return u'%s\n\n<!--\n%s\n-->' % (
+ render_traceback(self, full=full),
+ self.render_as_text().decode('utf-8', 'replace')
+ )
+
+ @property
+ def is_template_syntax_error(self):
+ """`True` if this is a template syntax error."""
+ return isinstance(self.exc_value, TemplateSyntaxError)
+
+ @property
+ def exc_info(self):
+ """Exception info tuple with a proxy around the frame objects."""
+ return self.exc_type, self.exc_value, self.frames[0]
+
+ @property
+ def standard_exc_info(self):
+ """Standard python exc_info for re-raising"""
+ tb = self.frames[0]
+ # the frame will be an actual traceback (or transparent proxy) if
+ # we are on pypy or a python implementation with support for tproxy
+ if type(tb) is not TracebackType:
+ tb = tb.tb
+ return self.exc_type, self.exc_value, tb
+
+
+def make_traceback(exc_info, source_hint=None):
+ """Creates a processed traceback object from the exc_info."""
+ exc_type, exc_value, tb = exc_info
+ if isinstance(exc_value, TemplateSyntaxError):
+ exc_info = translate_syntax_error(exc_value, source_hint)
+ initial_skip = 0
+ else:
+ initial_skip = 1
+ return translate_exception(exc_info, initial_skip)
+
+
+def translate_syntax_error(error, source=None):
+ """Rewrites a syntax error to please traceback systems."""
+ error.source = source
+ error.translated = True
+ exc_info = (error.__class__, error, None)
+ filename = error.filename
+ if filename is None:
+ filename = '<unknown>'
+ return fake_exc_info(exc_info, filename, error.lineno)
+
+
+def translate_exception(exc_info, initial_skip=0):
+ """If passed an exc_info it will automatically rewrite the exceptions
+ all the way down to the correct line numbers and frames.
+ """
+ tb = exc_info[2]
+ frames = []
+
+ # skip some internal frames if wanted
+ for x in range(initial_skip):
+ if tb is not None:
+ tb = tb.tb_next
+ initial_tb = tb
+
+ while tb is not None:
+ # skip frames decorated with @internalcode. These are internal
+ # calls we can't avoid and that are useless in template debugging
+ # output.
+ if tb.tb_frame.f_code in internal_code:
+ tb = tb.tb_next
+ continue
+
+ # save a reference to the next frame if we override the current
+ # one with a faked one.
+ next = tb.tb_next
+
+ # fake template exceptions
+ template = tb.tb_frame.f_globals.get('__jinja_template__')
+ if template is not None:
+ lineno = template.get_corresponding_lineno(tb.tb_lineno)
+ tb = fake_exc_info(exc_info[:2] + (tb,), template.filename,
+ lineno)[2]
+
+ frames.append(make_frame_proxy(tb))
+ tb = next
+
+ # if we don't have any exceptions in the frames left, we have to
+ # reraise it unchanged.
+ # XXX: can we backup here? when could this happen?
+ if not frames:
+ reraise(exc_info[0], exc_info[1], exc_info[2])
+
+ return ProcessedTraceback(exc_info[0], exc_info[1], frames)
+
+
+def fake_exc_info(exc_info, filename, lineno):
+ """Helper for `translate_exception`."""
+ exc_type, exc_value, tb = exc_info
+
+ # figure the real context out
+ if tb is not None:
+ real_locals = tb.tb_frame.f_locals.copy()
+ ctx = real_locals.get('context')
+ if ctx:
+ locals = ctx.get_all()
+ else:
+ locals = {}
+ for name, value in iteritems(real_locals):
+ if name.startswith('l_') and value is not missing:
+ locals[name[2:]] = value
+
+ # if there is a local called __jinja_exception__, we get
+ # rid of it to not break the debug functionality.
+ locals.pop('__jinja_exception__', None)
+ else:
+ locals = {}
+
+ # assamble fake globals we need
+ globals = {
+ '__name__': filename,
+ '__file__': filename,
+ '__jinja_exception__': exc_info[:2],
+
+ # we don't want to keep the reference to the template around
+ # to not cause circular dependencies, but we mark it as Jinja
+ # frame for the ProcessedTraceback
+ '__jinja_template__': None
+ }
+
+ # and fake the exception
+ code = compile('\n' * (lineno - 1) + raise_helper, filename, 'exec')
+
+ # if it's possible, change the name of the code. This won't work
+ # on some python environments such as google appengine
+ try:
+ if tb is None:
+ location = 'template'
+ else:
+ function = tb.tb_frame.f_code.co_name
+ if function == 'root':
+ location = 'top-level template code'
+ elif function.startswith('block_'):
+ location = 'block "%s"' % function[6:]
+ else:
+ location = 'template'
+
+ if PY2:
+ code = CodeType(0, code.co_nlocals, code.co_stacksize,
+ code.co_flags, code.co_code, code.co_consts,
+ code.co_names, code.co_varnames, filename,
+ location, code.co_firstlineno,
+ code.co_lnotab, (), ())
+ else:
+ code = CodeType(0, code.co_kwonlyargcount,
+ code.co_nlocals, code.co_stacksize,
+ code.co_flags, code.co_code, code.co_consts,
+ code.co_names, code.co_varnames, filename,
+ location, code.co_firstlineno,
+ code.co_lnotab, (), ())
+ except Exception as e:
+ pass
+
+ # execute the code and catch the new traceback
+ try:
+ exec(code, globals, locals)
+ except:
+ exc_info = sys.exc_info()
+ new_tb = exc_info[2].tb_next
+
+ # return without this frame
+ return exc_info[:2] + (new_tb,)
+
+
+def _init_ugly_crap():
+ """This function implements a few ugly things so that we can patch the
+ traceback objects. The function returned allows resetting `tb_next` on
+ any python traceback object. Do not attempt to use this on non cpython
+ interpreters
+ """
+ import ctypes
+ from types import TracebackType
+
+ if PY2:
+ # figure out size of _Py_ssize_t for Python 2:
+ if hasattr(ctypes.pythonapi, 'Py_InitModule4_64'):
+ _Py_ssize_t = ctypes.c_int64
+ else:
+ _Py_ssize_t = ctypes.c_int
+ else:
+ # platform ssize_t on Python 3
+ _Py_ssize_t = ctypes.c_ssize_t
+
+ # regular python
+ class _PyObject(ctypes.Structure):
+ pass
+ _PyObject._fields_ = [
+ ('ob_refcnt', _Py_ssize_t),
+ ('ob_type', ctypes.POINTER(_PyObject))
+ ]
+
+ # python with trace
+ if hasattr(sys, 'getobjects'):
+ class _PyObject(ctypes.Structure):
+ pass
+ _PyObject._fields_ = [
+ ('_ob_next', ctypes.POINTER(_PyObject)),
+ ('_ob_prev', ctypes.POINTER(_PyObject)),
+ ('ob_refcnt', _Py_ssize_t),
+ ('ob_type', ctypes.POINTER(_PyObject))
+ ]
+
+ class _Traceback(_PyObject):
+ pass
+ _Traceback._fields_ = [
+ ('tb_next', ctypes.POINTER(_Traceback)),
+ ('tb_frame', ctypes.POINTER(_PyObject)),
+ ('tb_lasti', ctypes.c_int),
+ ('tb_lineno', ctypes.c_int)
+ ]
+
+ def tb_set_next(tb, next):
+ """Set the tb_next attribute of a traceback object."""
+ if not (isinstance(tb, TracebackType) and
+ (next is None or isinstance(next, TracebackType))):
+ raise TypeError('tb_set_next arguments must be traceback objects')
+ obj = _Traceback.from_address(id(tb))
+ if tb.tb_next is not None:
+ old = _Traceback.from_address(id(tb.tb_next))
+ old.ob_refcnt -= 1
+ if next is None:
+ obj.tb_next = ctypes.POINTER(_Traceback)()
+ else:
+ next = _Traceback.from_address(id(next))
+ next.ob_refcnt += 1
+ obj.tb_next = ctypes.pointer(next)
+
+ return tb_set_next
+
+
+# try to get a tb_set_next implementation if we don't have transparent
+# proxies.
+tb_set_next = None
+if tproxy is None:
+ try:
+ tb_set_next = _init_ugly_crap()
+ except:
+ pass
+ del _init_ugly_crap
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/defaults.py b/deps/v8_inspector/deps/jinja2/jinja2/defaults.py
new file mode 100644
index 0000000000..3717a7223f
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/defaults.py
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.defaults
+ ~~~~~~~~~~~~~~~
+
+ Jinja default filters and tags.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+from jinja2._compat import range_type
+from jinja2.utils import generate_lorem_ipsum, Cycler, Joiner
+
+
+# defaults for the parser / lexer
+BLOCK_START_STRING = '{%'
+BLOCK_END_STRING = '%}'
+VARIABLE_START_STRING = '{{'
+VARIABLE_END_STRING = '}}'
+COMMENT_START_STRING = '{#'
+COMMENT_END_STRING = '#}'
+LINE_STATEMENT_PREFIX = None
+LINE_COMMENT_PREFIX = None
+TRIM_BLOCKS = False
+LSTRIP_BLOCKS = False
+NEWLINE_SEQUENCE = '\n'
+KEEP_TRAILING_NEWLINE = False
+
+
+# default filters, tests and namespace
+from jinja2.filters import FILTERS as DEFAULT_FILTERS
+from jinja2.tests import TESTS as DEFAULT_TESTS
+DEFAULT_NAMESPACE = {
+ 'range': range_type,
+ 'dict': dict,
+ 'lipsum': generate_lorem_ipsum,
+ 'cycler': Cycler,
+ 'joiner': Joiner
+}
+
+
+# export all constants
+__all__ = tuple(x for x in locals().keys() if x.isupper())
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/environment.py b/deps/v8_inspector/deps/jinja2/jinja2/environment.py
new file mode 100644
index 0000000000..8b2572bb8c
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/environment.py
@@ -0,0 +1,1213 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.environment
+ ~~~~~~~~~~~~~~~~~~
+
+ Provides a class that holds runtime and parsing time options.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import os
+import sys
+from jinja2 import nodes
+from jinja2.defaults import BLOCK_START_STRING, \
+ BLOCK_END_STRING, VARIABLE_START_STRING, VARIABLE_END_STRING, \
+ COMMENT_START_STRING, COMMENT_END_STRING, LINE_STATEMENT_PREFIX, \
+ LINE_COMMENT_PREFIX, TRIM_BLOCKS, NEWLINE_SEQUENCE, \
+ DEFAULT_FILTERS, DEFAULT_TESTS, DEFAULT_NAMESPACE, \
+ KEEP_TRAILING_NEWLINE, LSTRIP_BLOCKS
+from jinja2.lexer import get_lexer, TokenStream
+from jinja2.parser import Parser
+from jinja2.nodes import EvalContext
+from jinja2.optimizer import optimize
+from jinja2.compiler import generate, CodeGenerator
+from jinja2.runtime import Undefined, new_context, Context
+from jinja2.exceptions import TemplateSyntaxError, TemplateNotFound, \
+ TemplatesNotFound, TemplateRuntimeError
+from jinja2.utils import import_string, LRUCache, Markup, missing, \
+ concat, consume, internalcode
+from jinja2._compat import imap, ifilter, string_types, iteritems, \
+ text_type, reraise, implements_iterator, implements_to_string, \
+ get_next, encode_filename, PY2, PYPY
+from functools import reduce
+
+
+# for direct template usage we have up to ten living environments
+_spontaneous_environments = LRUCache(10)
+
+# the function to create jinja traceback objects. This is dynamically
+# imported on the first exception in the exception handler.
+_make_traceback = None
+
+
+def get_spontaneous_environment(*args):
+ """Return a new spontaneous environment. A spontaneous environment is an
+ unnamed and unaccessible (in theory) environment that is used for
+ templates generated from a string and not from the file system.
+ """
+ try:
+ env = _spontaneous_environments.get(args)
+ except TypeError:
+ return Environment(*args)
+ if env is not None:
+ return env
+ _spontaneous_environments[args] = env = Environment(*args)
+ env.shared = True
+ return env
+
+
+def create_cache(size):
+ """Return the cache class for the given size."""
+ if size == 0:
+ return None
+ if size < 0:
+ return {}
+ return LRUCache(size)
+
+
+def copy_cache(cache):
+ """Create an empty copy of the given cache."""
+ if cache is None:
+ return None
+ elif type(cache) is dict:
+ return {}
+ return LRUCache(cache.capacity)
+
+
+def load_extensions(environment, extensions):
+ """Load the extensions from the list and bind it to the environment.
+ Returns a dict of instantiated environments.
+ """
+ result = {}
+ for extension in extensions:
+ if isinstance(extension, string_types):
+ extension = import_string(extension)
+ result[extension.identifier] = extension(environment)
+ return result
+
+
+def _environment_sanity_check(environment):
+ """Perform a sanity check on the environment."""
+ assert issubclass(environment.undefined, Undefined), 'undefined must ' \
+ 'be a subclass of undefined because filters depend on it.'
+ assert environment.block_start_string != \
+ environment.variable_start_string != \
+ environment.comment_start_string, 'block, variable and comment ' \
+ 'start strings must be different'
+ assert environment.newline_sequence in ('\r', '\r\n', '\n'), \
+ 'newline_sequence set to unknown line ending string.'
+ return environment
+
+
+class Environment(object):
+ r"""The core component of Jinja is the `Environment`. It contains
+ important shared variables like configuration, filters, tests,
+ globals and others. Instances of this class may be modified if
+ they are not shared and if no template was loaded so far.
+ Modifications on environments after the first template was loaded
+ will lead to surprising effects and undefined behavior.
+
+ Here are the possible initialization parameters:
+
+ `block_start_string`
+ The string marking the beginning of a block. Defaults to ``'{%'``.
+
+ `block_end_string`
+ The string marking the end of a block. Defaults to ``'%}'``.
+
+ `variable_start_string`
+ The string marking the beginning of a print statement.
+ Defaults to ``'{{'``.
+
+ `variable_end_string`
+ The string marking the end of a print statement. Defaults to
+ ``'}}'``.
+
+ `comment_start_string`
+ The string marking the beginning of a comment. Defaults to ``'{#'``.
+
+ `comment_end_string`
+ The string marking the end of a comment. Defaults to ``'#}'``.
+
+ `line_statement_prefix`
+ If given and a string, this will be used as prefix for line based
+ statements. See also :ref:`line-statements`.
+
+ `line_comment_prefix`
+ If given and a string, this will be used as prefix for line based
+ comments. See also :ref:`line-statements`.
+
+ .. versionadded:: 2.2
+
+ `trim_blocks`
+ If this is set to ``True`` the first newline after a block is
+ removed (block, not variable tag!). Defaults to `False`.
+
+ `lstrip_blocks`
+ If this is set to ``True`` leading spaces and tabs are stripped
+ from the start of a line to a block. Defaults to `False`.
+
+ `newline_sequence`
+ The sequence that starts a newline. Must be one of ``'\r'``,
+ ``'\n'`` or ``'\r\n'``. The default is ``'\n'`` which is a
+ useful default for Linux and OS X systems as well as web
+ applications.
+
+ `keep_trailing_newline`
+ Preserve the trailing newline when rendering templates.
+ The default is ``False``, which causes a single newline,
+ if present, to be stripped from the end of the template.
+
+ .. versionadded:: 2.7
+
+ `extensions`
+ List of Jinja extensions to use. This can either be import paths
+ as strings or extension classes. For more information have a
+ look at :ref:`the extensions documentation <jinja-extensions>`.
+
+ `optimized`
+ should the optimizer be enabled? Default is `True`.
+
+ `undefined`
+ :class:`Undefined` or a subclass of it that is used to represent
+ undefined values in the template.
+
+ `finalize`
+ A callable that can be used to process the result of a variable
+ expression before it is output. For example one can convert
+ `None` implicitly into an empty string here.
+
+ `autoescape`
+ If set to true the XML/HTML autoescaping feature is enabled by
+ default. For more details about autoescaping see
+ :class:`~jinja2.utils.Markup`. As of Jinja 2.4 this can also
+ be a callable that is passed the template name and has to
+ return `True` or `False` depending on autoescape should be
+ enabled by default.
+
+ .. versionchanged:: 2.4
+ `autoescape` can now be a function
+
+ `loader`
+ The template loader for this environment.
+
+ `cache_size`
+ The size of the cache. Per default this is ``400`` which means
+ that if more than 400 templates are loaded the loader will clean
+ out the least recently used template. If the cache size is set to
+ ``0`` templates are recompiled all the time, if the cache size is
+ ``-1`` the cache will not be cleaned.
+
+ .. versionchanged:: 2.8
+ The cache size was increased to 400 from a low 50.
+
+ `auto_reload`
+ Some loaders load templates from locations where the template
+ sources may change (ie: file system or database). If
+ `auto_reload` is set to `True` (default) every time a template is
+ requested the loader checks if the source changed and if yes, it
+ will reload the template. For higher performance it's possible to
+ disable that.
+
+ `bytecode_cache`
+ If set to a bytecode cache object, this object will provide a
+ cache for the internal Jinja bytecode so that templates don't
+ have to be parsed if they were not changed.
+
+ See :ref:`bytecode-cache` for more information.
+ """
+
+ #: if this environment is sandboxed. Modifying this variable won't make
+ #: the environment sandboxed though. For a real sandboxed environment
+ #: have a look at jinja2.sandbox. This flag alone controls the code
+ #: generation by the compiler.
+ sandboxed = False
+
+ #: True if the environment is just an overlay
+ overlayed = False
+
+ #: the environment this environment is linked to if it is an overlay
+ linked_to = None
+
+ #: shared environments have this set to `True`. A shared environment
+ #: must not be modified
+ shared = False
+
+ #: these are currently EXPERIMENTAL undocumented features.
+ exception_handler = None
+ exception_formatter = None
+
+ #: the class that is used for code generation. See
+ #: :class:`~jinja2.compiler.CodeGenerator` for more information.
+ code_generator_class = CodeGenerator
+
+ #: the context class thatis used for templates. See
+ #: :class:`~jinja2.runtime.Context` for more information.
+ context_class = Context
+
+ def __init__(self,
+ block_start_string=BLOCK_START_STRING,
+ block_end_string=BLOCK_END_STRING,
+ variable_start_string=VARIABLE_START_STRING,
+ variable_end_string=VARIABLE_END_STRING,
+ comment_start_string=COMMENT_START_STRING,
+ comment_end_string=COMMENT_END_STRING,
+ line_statement_prefix=LINE_STATEMENT_PREFIX,
+ line_comment_prefix=LINE_COMMENT_PREFIX,
+ trim_blocks=TRIM_BLOCKS,
+ lstrip_blocks=LSTRIP_BLOCKS,
+ newline_sequence=NEWLINE_SEQUENCE,
+ keep_trailing_newline=KEEP_TRAILING_NEWLINE,
+ extensions=(),
+ optimized=True,
+ undefined=Undefined,
+ finalize=None,
+ autoescape=False,
+ loader=None,
+ cache_size=400,
+ auto_reload=True,
+ bytecode_cache=None):
+ # !!Important notice!!
+ # The constructor accepts quite a few arguments that should be
+ # passed by keyword rather than position. However it's important to
+ # not change the order of arguments because it's used at least
+ # internally in those cases:
+ # - spontaneous environments (i18n extension and Template)
+ # - unittests
+ # If parameter changes are required only add parameters at the end
+ # and don't change the arguments (or the defaults!) of the arguments
+ # existing already.
+
+ # lexer / parser information
+ self.block_start_string = block_start_string
+ self.block_end_string = block_end_string
+ self.variable_start_string = variable_start_string
+ self.variable_end_string = variable_end_string
+ self.comment_start_string = comment_start_string
+ self.comment_end_string = comment_end_string
+ self.line_statement_prefix = line_statement_prefix
+ self.line_comment_prefix = line_comment_prefix
+ self.trim_blocks = trim_blocks
+ self.lstrip_blocks = lstrip_blocks
+ self.newline_sequence = newline_sequence
+ self.keep_trailing_newline = keep_trailing_newline
+
+ # runtime information
+ self.undefined = undefined
+ self.optimized = optimized
+ self.finalize = finalize
+ self.autoescape = autoescape
+
+ # defaults
+ self.filters = DEFAULT_FILTERS.copy()
+ self.tests = DEFAULT_TESTS.copy()
+ self.globals = DEFAULT_NAMESPACE.copy()
+
+ # set the loader provided
+ self.loader = loader
+ self.cache = create_cache(cache_size)
+ self.bytecode_cache = bytecode_cache
+ self.auto_reload = auto_reload
+
+ # load extensions
+ self.extensions = load_extensions(self, extensions)
+
+ _environment_sanity_check(self)
+
+ def add_extension(self, extension):
+ """Adds an extension after the environment was created.
+
+ .. versionadded:: 2.5
+ """
+ self.extensions.update(load_extensions(self, [extension]))
+
+ def extend(self, **attributes):
+ """Add the items to the instance of the environment if they do not exist
+ yet. This is used by :ref:`extensions <writing-extensions>` to register
+ callbacks and configuration values without breaking inheritance.
+ """
+ for key, value in iteritems(attributes):
+ if not hasattr(self, key):
+ setattr(self, key, value)
+
+ def overlay(self, block_start_string=missing, block_end_string=missing,
+ variable_start_string=missing, variable_end_string=missing,
+ comment_start_string=missing, comment_end_string=missing,
+ line_statement_prefix=missing, line_comment_prefix=missing,
+ trim_blocks=missing, lstrip_blocks=missing,
+ extensions=missing, optimized=missing,
+ undefined=missing, finalize=missing, autoescape=missing,
+ loader=missing, cache_size=missing, auto_reload=missing,
+ bytecode_cache=missing):
+ """Create a new overlay environment that shares all the data with the
+ current environment except for cache and the overridden attributes.
+ Extensions cannot be removed for an overlayed environment. An overlayed
+ environment automatically gets all the extensions of the environment it
+ is linked to plus optional extra extensions.
+
+ Creating overlays should happen after the initial environment was set
+ up completely. Not all attributes are truly linked, some are just
+ copied over so modifications on the original environment may not shine
+ through.
+ """
+ args = dict(locals())
+ del args['self'], args['cache_size'], args['extensions']
+
+ rv = object.__new__(self.__class__)
+ rv.__dict__.update(self.__dict__)
+ rv.overlayed = True
+ rv.linked_to = self
+
+ for key, value in iteritems(args):
+ if value is not missing:
+ setattr(rv, key, value)
+
+ if cache_size is not missing:
+ rv.cache = create_cache(cache_size)
+ else:
+ rv.cache = copy_cache(self.cache)
+
+ rv.extensions = {}
+ for key, value in iteritems(self.extensions):
+ rv.extensions[key] = value.bind(rv)
+ if extensions is not missing:
+ rv.extensions.update(load_extensions(rv, extensions))
+
+ return _environment_sanity_check(rv)
+
+ lexer = property(get_lexer, doc="The lexer for this environment.")
+
+ def iter_extensions(self):
+ """Iterates over the extensions by priority."""
+ return iter(sorted(self.extensions.values(),
+ key=lambda x: x.priority))
+
+ def getitem(self, obj, argument):
+ """Get an item or attribute of an object but prefer the item."""
+ try:
+ return obj[argument]
+ except (TypeError, LookupError):
+ if isinstance(argument, string_types):
+ try:
+ attr = str(argument)
+ except Exception:
+ pass
+ else:
+ try:
+ return getattr(obj, attr)
+ except AttributeError:
+ pass
+ return self.undefined(obj=obj, name=argument)
+
+ def getattr(self, obj, attribute):
+ """Get an item or attribute of an object but prefer the attribute.
+ Unlike :meth:`getitem` the attribute *must* be a bytestring.
+ """
+ try:
+ return getattr(obj, attribute)
+ except AttributeError:
+ pass
+ try:
+ return obj[attribute]
+ except (TypeError, LookupError, AttributeError):
+ return self.undefined(obj=obj, name=attribute)
+
+ def call_filter(self, name, value, args=None, kwargs=None,
+ context=None, eval_ctx=None):
+ """Invokes a filter on a value the same way the compiler does it.
+
+ .. versionadded:: 2.7
+ """
+ func = self.filters.get(name)
+ if func is None:
+ raise TemplateRuntimeError('no filter named %r' % name)
+ args = [value] + list(args or ())
+ if getattr(func, 'contextfilter', False):
+ if context is None:
+ raise TemplateRuntimeError('Attempted to invoke context '
+ 'filter without context')
+ args.insert(0, context)
+ elif getattr(func, 'evalcontextfilter', False):
+ if eval_ctx is None:
+ if context is not None:
+ eval_ctx = context.eval_ctx
+ else:
+ eval_ctx = EvalContext(self)
+ args.insert(0, eval_ctx)
+ elif getattr(func, 'environmentfilter', False):
+ args.insert(0, self)
+ return func(*args, **(kwargs or {}))
+
+ def call_test(self, name, value, args=None, kwargs=None):
+ """Invokes a test on a value the same way the compiler does it.
+
+ .. versionadded:: 2.7
+ """
+ func = self.tests.get(name)
+ if func is None:
+ raise TemplateRuntimeError('no test named %r' % name)
+ return func(value, *(args or ()), **(kwargs or {}))
+
+ @internalcode
+ def parse(self, source, name=None, filename=None):
+ """Parse the sourcecode and return the abstract syntax tree. This
+ tree of nodes is used by the compiler to convert the template into
+ executable source- or bytecode. This is useful for debugging or to
+ extract information from templates.
+
+ If you are :ref:`developing Jinja2 extensions <writing-extensions>`
+ this gives you a good overview of the node tree generated.
+ """
+ try:
+ return self._parse(source, name, filename)
+ except TemplateSyntaxError:
+ exc_info = sys.exc_info()
+ self.handle_exception(exc_info, source_hint=source)
+
+ def _parse(self, source, name, filename):
+ """Internal parsing function used by `parse` and `compile`."""
+ return Parser(self, source, name, encode_filename(filename)).parse()
+
+ def lex(self, source, name=None, filename=None):
+ """Lex the given sourcecode and return a generator that yields
+ tokens as tuples in the form ``(lineno, token_type, value)``.
+ This can be useful for :ref:`extension development <writing-extensions>`
+ and debugging templates.
+
+ This does not perform preprocessing. If you want the preprocessing
+ of the extensions to be applied you have to filter source through
+ the :meth:`preprocess` method.
+ """
+ source = text_type(source)
+ try:
+ return self.lexer.tokeniter(source, name, filename)
+ except TemplateSyntaxError:
+ exc_info = sys.exc_info()
+ self.handle_exception(exc_info, source_hint=source)
+
+ def preprocess(self, source, name=None, filename=None):
+ """Preprocesses the source with all extensions. This is automatically
+ called for all parsing and compiling methods but *not* for :meth:`lex`
+ because there you usually only want the actual source tokenized.
+ """
+ return reduce(lambda s, e: e.preprocess(s, name, filename),
+ self.iter_extensions(), text_type(source))
+
+ def _tokenize(self, source, name, filename=None, state=None):
+ """Called by the parser to do the preprocessing and filtering
+ for all the extensions. Returns a :class:`~jinja2.lexer.TokenStream`.
+ """
+ source = self.preprocess(source, name, filename)
+ stream = self.lexer.tokenize(source, name, filename, state)
+ for ext in self.iter_extensions():
+ stream = ext.filter_stream(stream)
+ if not isinstance(stream, TokenStream):
+ stream = TokenStream(stream, name, filename)
+ return stream
+
+ def _generate(self, source, name, filename, defer_init=False):
+ """Internal hook that can be overridden to hook a different generate
+ method in.
+
+ .. versionadded:: 2.5
+ """
+ return generate(source, self, name, filename, defer_init=defer_init)
+
+ def _compile(self, source, filename):
+ """Internal hook that can be overridden to hook a different compile
+ method in.
+
+ .. versionadded:: 2.5
+ """
+ return compile(source, filename, 'exec')
+
+ @internalcode
+ def compile(self, source, name=None, filename=None, raw=False,
+ defer_init=False):
+ """Compile a node or template source code. The `name` parameter is
+ the load name of the template after it was joined using
+ :meth:`join_path` if necessary, not the filename on the file system.
+ the `filename` parameter is the estimated filename of the template on
+ the file system. If the template came from a database or memory this
+ can be omitted.
+
+ The return value of this method is a python code object. If the `raw`
+ parameter is `True` the return value will be a string with python
+ code equivalent to the bytecode returned otherwise. This method is
+ mainly used internally.
+
+ `defer_init` is use internally to aid the module code generator. This
+ causes the generated code to be able to import without the global
+ environment variable to be set.
+
+ .. versionadded:: 2.4
+ `defer_init` parameter added.
+ """
+ source_hint = None
+ try:
+ if isinstance(source, string_types):
+ source_hint = source
+ source = self._parse(source, name, filename)
+ if self.optimized:
+ source = optimize(source, self)
+ source = self._generate(source, name, filename,
+ defer_init=defer_init)
+ if raw:
+ return source
+ if filename is None:
+ filename = '<template>'
+ else:
+ filename = encode_filename(filename)
+ return self._compile(source, filename)
+ except TemplateSyntaxError:
+ exc_info = sys.exc_info()
+ self.handle_exception(exc_info, source_hint=source_hint)
+
+ def compile_expression(self, source, undefined_to_none=True):
+ """A handy helper method that returns a callable that accepts keyword
+ arguments that appear as variables in the expression. If called it
+ returns the result of the expression.
+
+ This is useful if applications want to use the same rules as Jinja
+ in template "configuration files" or similar situations.
+
+ Example usage:
+
+ >>> env = Environment()
+ >>> expr = env.compile_expression('foo == 42')
+ >>> expr(foo=23)
+ False
+ >>> expr(foo=42)
+ True
+
+ Per default the return value is converted to `None` if the
+ expression returns an undefined value. This can be changed
+ by setting `undefined_to_none` to `False`.
+
+ >>> env.compile_expression('var')() is None
+ True
+ >>> env.compile_expression('var', undefined_to_none=False)()
+ Undefined
+
+ .. versionadded:: 2.1
+ """
+ parser = Parser(self, source, state='variable')
+ exc_info = None
+ try:
+ expr = parser.parse_expression()
+ if not parser.stream.eos:
+ raise TemplateSyntaxError('chunk after expression',
+ parser.stream.current.lineno,
+ None, None)
+ expr.set_environment(self)
+ except TemplateSyntaxError:
+ exc_info = sys.exc_info()
+ if exc_info is not None:
+ self.handle_exception(exc_info, source_hint=source)
+ body = [nodes.Assign(nodes.Name('result', 'store'), expr, lineno=1)]
+ template = self.from_string(nodes.Template(body, lineno=1))
+ return TemplateExpression(template, undefined_to_none)
+
+ def compile_templates(self, target, extensions=None, filter_func=None,
+ zip='deflated', log_function=None,
+ ignore_errors=True, py_compile=False):
+ """Finds all the templates the loader can find, compiles them
+ and stores them in `target`. If `zip` is `None`, instead of in a
+ zipfile, the templates will be stored in a directory.
+ By default a deflate zip algorithm is used. To switch to
+ the stored algorithm, `zip` can be set to ``'stored'``.
+
+ `extensions` and `filter_func` are passed to :meth:`list_templates`.
+ Each template returned will be compiled to the target folder or
+ zipfile.
+
+ By default template compilation errors are ignored. In case a
+ log function is provided, errors are logged. If you want template
+ syntax errors to abort the compilation you can set `ignore_errors`
+ to `False` and you will get an exception on syntax errors.
+
+ If `py_compile` is set to `True` .pyc files will be written to the
+ target instead of standard .py files. This flag does not do anything
+ on pypy and Python 3 where pyc files are not picked up by itself and
+ don't give much benefit.
+
+ .. versionadded:: 2.4
+ """
+ from jinja2.loaders import ModuleLoader
+
+ if log_function is None:
+ log_function = lambda x: None
+
+ if py_compile:
+ if not PY2 or PYPY:
+ from warnings import warn
+ warn(Warning('py_compile has no effect on pypy or Python 3'))
+ py_compile = False
+ else:
+ import imp
+ import marshal
+ py_header = imp.get_magic() + \
+ u'\xff\xff\xff\xff'.encode('iso-8859-15')
+
+ # Python 3.3 added a source filesize to the header
+ if sys.version_info >= (3, 3):
+ py_header += u'\x00\x00\x00\x00'.encode('iso-8859-15')
+
+ def write_file(filename, data, mode):
+ if zip:
+ info = ZipInfo(filename)
+ info.external_attr = 0o755 << 16
+ zip_file.writestr(info, data)
+ else:
+ f = open(os.path.join(target, filename), mode)
+ try:
+ f.write(data)
+ finally:
+ f.close()
+
+ if zip is not None:
+ from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED, ZIP_STORED
+ zip_file = ZipFile(target, 'w', dict(deflated=ZIP_DEFLATED,
+ stored=ZIP_STORED)[zip])
+ log_function('Compiling into Zip archive "%s"' % target)
+ else:
+ if not os.path.isdir(target):
+ os.makedirs(target)
+ log_function('Compiling into folder "%s"' % target)
+
+ try:
+ for name in self.list_templates(extensions, filter_func):
+ source, filename, _ = self.loader.get_source(self, name)
+ try:
+ code = self.compile(source, name, filename, True, True)
+ except TemplateSyntaxError as e:
+ if not ignore_errors:
+ raise
+ log_function('Could not compile "%s": %s' % (name, e))
+ continue
+
+ filename = ModuleLoader.get_module_filename(name)
+
+ if py_compile:
+ c = self._compile(code, encode_filename(filename))
+ write_file(filename + 'c', py_header +
+ marshal.dumps(c), 'wb')
+ log_function('Byte-compiled "%s" as %s' %
+ (name, filename + 'c'))
+ else:
+ write_file(filename, code, 'w')
+ log_function('Compiled "%s" as %s' % (name, filename))
+ finally:
+ if zip:
+ zip_file.close()
+
+ log_function('Finished compiling templates')
+
+ def list_templates(self, extensions=None, filter_func=None):
+ """Returns a list of templates for this environment. This requires
+ that the loader supports the loader's
+ :meth:`~BaseLoader.list_templates` method.
+
+ If there are other files in the template folder besides the
+ actual templates, the returned list can be filtered. There are two
+ ways: either `extensions` is set to a list of file extensions for
+ templates, or a `filter_func` can be provided which is a callable that
+ is passed a template name and should return `True` if it should end up
+ in the result list.
+
+ If the loader does not support that, a :exc:`TypeError` is raised.
+
+ .. versionadded:: 2.4
+ """
+ x = self.loader.list_templates()
+ if extensions is not None:
+ if filter_func is not None:
+ raise TypeError('either extensions or filter_func '
+ 'can be passed, but not both')
+ filter_func = lambda x: '.' in x and \
+ x.rsplit('.', 1)[1] in extensions
+ if filter_func is not None:
+ x = list(ifilter(filter_func, x))
+ return x
+
+ def handle_exception(self, exc_info=None, rendered=False, source_hint=None):
+ """Exception handling helper. This is used internally to either raise
+ rewritten exceptions or return a rendered traceback for the template.
+ """
+ global _make_traceback
+ if exc_info is None:
+ exc_info = sys.exc_info()
+
+ # the debugging module is imported when it's used for the first time.
+ # we're doing a lot of stuff there and for applications that do not
+ # get any exceptions in template rendering there is no need to load
+ # all of that.
+ if _make_traceback is None:
+ from jinja2.debug import make_traceback as _make_traceback
+ traceback = _make_traceback(exc_info, source_hint)
+ if rendered and self.exception_formatter is not None:
+ return self.exception_formatter(traceback)
+ if self.exception_handler is not None:
+ self.exception_handler(traceback)
+ exc_type, exc_value, tb = traceback.standard_exc_info
+ reraise(exc_type, exc_value, tb)
+
+ def join_path(self, template, parent):
+ """Join a template with the parent. By default all the lookups are
+ relative to the loader root so this method returns the `template`
+ parameter unchanged, but if the paths should be relative to the
+ parent template, this function can be used to calculate the real
+ template name.
+
+ Subclasses may override this method and implement template path
+ joining here.
+ """
+ return template
+
+ @internalcode
+ def _load_template(self, name, globals):
+ if self.loader is None:
+ raise TypeError('no loader for this environment specified')
+ try:
+ # use abs path for cache key
+ cache_key = self.loader.get_source(self, name)[1]
+ except RuntimeError:
+ # if loader does not implement get_source()
+ cache_key = None
+ # if template is not file, use name for cache key
+ if cache_key is None:
+ cache_key = name
+ if self.cache is not None:
+ template = self.cache.get(cache_key)
+ if template is not None and (not self.auto_reload or
+ template.is_up_to_date):
+ return template
+ template = self.loader.load(self, name, globals)
+ if self.cache is not None:
+ self.cache[cache_key] = template
+ return template
+
+ @internalcode
+ def get_template(self, name, parent=None, globals=None):
+ """Load a template from the loader. If a loader is configured this
+ method ask the loader for the template and returns a :class:`Template`.
+ If the `parent` parameter is not `None`, :meth:`join_path` is called
+ to get the real template name before loading.
+
+ The `globals` parameter can be used to provide template wide globals.
+ These variables are available in the context at render time.
+
+ If the template does not exist a :exc:`TemplateNotFound` exception is
+ raised.
+
+ .. versionchanged:: 2.4
+ If `name` is a :class:`Template` object it is returned from the
+ function unchanged.
+ """
+ if isinstance(name, Template):
+ return name
+ if parent is not None:
+ name = self.join_path(name, parent)
+ return self._load_template(name, self.make_globals(globals))
+
+ @internalcode
+ def select_template(self, names, parent=None, globals=None):
+ """Works like :meth:`get_template` but tries a number of templates
+ before it fails. If it cannot find any of the templates, it will
+ raise a :exc:`TemplatesNotFound` exception.
+
+ .. versionadded:: 2.3
+
+ .. versionchanged:: 2.4
+ If `names` contains a :class:`Template` object it is returned
+ from the function unchanged.
+ """
+ if not names:
+ raise TemplatesNotFound(message=u'Tried to select from an empty list '
+ u'of templates.')
+ globals = self.make_globals(globals)
+ for name in names:
+ if isinstance(name, Template):
+ return name
+ if parent is not None:
+ name = self.join_path(name, parent)
+ try:
+ return self._load_template(name, globals)
+ except TemplateNotFound:
+ pass
+ raise TemplatesNotFound(names)
+
+ @internalcode
+ def get_or_select_template(self, template_name_or_list,
+ parent=None, globals=None):
+ """Does a typecheck and dispatches to :meth:`select_template`
+ if an iterable of template names is given, otherwise to
+ :meth:`get_template`.
+
+ .. versionadded:: 2.3
+ """
+ if isinstance(template_name_or_list, string_types):
+ return self.get_template(template_name_or_list, parent, globals)
+ elif isinstance(template_name_or_list, Template):
+ return template_name_or_list
+ return self.select_template(template_name_or_list, parent, globals)
+
+ def from_string(self, source, globals=None, template_class=None):
+ """Load a template from a string. This parses the source given and
+ returns a :class:`Template` object.
+ """
+ globals = self.make_globals(globals)
+ cls = template_class or self.template_class
+ return cls.from_code(self, self.compile(source), globals, None)
+
+ def make_globals(self, d):
+ """Return a dict for the globals."""
+ if not d:
+ return self.globals
+ return dict(self.globals, **d)
+
+
+class Template(object):
+ """The central template object. This class represents a compiled template
+ and is used to evaluate it.
+
+ Normally the template object is generated from an :class:`Environment` but
+ it also has a constructor that makes it possible to create a template
+ instance directly using the constructor. It takes the same arguments as
+ the environment constructor but it's not possible to specify a loader.
+
+ Every template object has a few methods and members that are guaranteed
+ to exist. However it's important that a template object should be
+ considered immutable. Modifications on the object are not supported.
+
+ Template objects created from the constructor rather than an environment
+ do have an `environment` attribute that points to a temporary environment
+ that is probably shared with other templates created with the constructor
+ and compatible settings.
+
+ >>> template = Template('Hello {{ name }}!')
+ >>> template.render(name='John Doe') == u'Hello John Doe!'
+ True
+ >>> stream = template.stream(name='John Doe')
+ >>> next(stream) == u'Hello John Doe!'
+ True
+ >>> next(stream)
+ Traceback (most recent call last):
+ ...
+ StopIteration
+ """
+
+ def __new__(cls, source,
+ block_start_string=BLOCK_START_STRING,
+ block_end_string=BLOCK_END_STRING,
+ variable_start_string=VARIABLE_START_STRING,
+ variable_end_string=VARIABLE_END_STRING,
+ comment_start_string=COMMENT_START_STRING,
+ comment_end_string=COMMENT_END_STRING,
+ line_statement_prefix=LINE_STATEMENT_PREFIX,
+ line_comment_prefix=LINE_COMMENT_PREFIX,
+ trim_blocks=TRIM_BLOCKS,
+ lstrip_blocks=LSTRIP_BLOCKS,
+ newline_sequence=NEWLINE_SEQUENCE,
+ keep_trailing_newline=KEEP_TRAILING_NEWLINE,
+ extensions=(),
+ optimized=True,
+ undefined=Undefined,
+ finalize=None,
+ autoescape=False):
+ env = get_spontaneous_environment(
+ block_start_string, block_end_string, variable_start_string,
+ variable_end_string, comment_start_string, comment_end_string,
+ line_statement_prefix, line_comment_prefix, trim_blocks,
+ lstrip_blocks, newline_sequence, keep_trailing_newline,
+ frozenset(extensions), optimized, undefined, finalize, autoescape,
+ None, 0, False, None)
+ return env.from_string(source, template_class=cls)
+
+ @classmethod
+ def from_code(cls, environment, code, globals, uptodate=None):
+ """Creates a template object from compiled code and the globals. This
+ is used by the loaders and environment to create a template object.
+ """
+ namespace = {
+ 'environment': environment,
+ '__file__': code.co_filename
+ }
+ exec(code, namespace)
+ rv = cls._from_namespace(environment, namespace, globals)
+ rv._uptodate = uptodate
+ return rv
+
+ @classmethod
+ def from_module_dict(cls, environment, module_dict, globals):
+ """Creates a template object from a module. This is used by the
+ module loader to create a template object.
+
+ .. versionadded:: 2.4
+ """
+ return cls._from_namespace(environment, module_dict, globals)
+
+ @classmethod
+ def _from_namespace(cls, environment, namespace, globals):
+ t = object.__new__(cls)
+ t.environment = environment
+ t.globals = globals
+ t.name = namespace['name']
+ t.filename = namespace['__file__']
+ t.blocks = namespace['blocks']
+
+ # render function and module
+ t.root_render_func = namespace['root']
+ t._module = None
+
+ # debug and loader helpers
+ t._debug_info = namespace['debug_info']
+ t._uptodate = None
+
+ # store the reference
+ namespace['environment'] = environment
+ namespace['__jinja_template__'] = t
+
+ return t
+
+ def render(self, *args, **kwargs):
+ """This method accepts the same arguments as the `dict` constructor:
+ A dict, a dict subclass or some keyword arguments. If no arguments
+ are given the context will be empty. These two calls do the same::
+
+ template.render(knights='that say nih')
+ template.render({'knights': 'that say nih'})
+
+ This will return the rendered template as unicode string.
+ """
+ vars = dict(*args, **kwargs)
+ try:
+ return concat(self.root_render_func(self.new_context(vars)))
+ except Exception:
+ exc_info = sys.exc_info()
+ return self.environment.handle_exception(exc_info, True)
+
+ def stream(self, *args, **kwargs):
+ """Works exactly like :meth:`generate` but returns a
+ :class:`TemplateStream`.
+ """
+ return TemplateStream(self.generate(*args, **kwargs))
+
+ def generate(self, *args, **kwargs):
+ """For very large templates it can be useful to not render the whole
+ template at once but evaluate each statement after another and yield
+ piece for piece. This method basically does exactly that and returns
+ a generator that yields one item after another as unicode strings.
+
+ It accepts the same arguments as :meth:`render`.
+ """
+ vars = dict(*args, **kwargs)
+ try:
+ for event in self.root_render_func(self.new_context(vars)):
+ yield event
+ except Exception:
+ exc_info = sys.exc_info()
+ else:
+ return
+ yield self.environment.handle_exception(exc_info, True)
+
+ def new_context(self, vars=None, shared=False, locals=None):
+ """Create a new :class:`Context` for this template. The vars
+ provided will be passed to the template. Per default the globals
+ are added to the context. If shared is set to `True` the data
+ is passed as it to the context without adding the globals.
+
+ `locals` can be a dict of local variables for internal usage.
+ """
+ return new_context(self.environment, self.name, self.blocks,
+ vars, shared, self.globals, locals)
+
+ def make_module(self, vars=None, shared=False, locals=None):
+ """This method works like the :attr:`module` attribute when called
+ without arguments but it will evaluate the template on every call
+ rather than caching it. It's also possible to provide
+ a dict which is then used as context. The arguments are the same
+ as for the :meth:`new_context` method.
+ """
+ return TemplateModule(self, self.new_context(vars, shared, locals))
+
+ @property
+ def module(self):
+ """The template as module. This is used for imports in the
+ template runtime but is also useful if one wants to access
+ exported template variables from the Python layer:
+
+ >>> t = Template('{% macro foo() %}42{% endmacro %}23')
+ >>> str(t.module)
+ '23'
+ >>> t.module.foo() == u'42'
+ True
+ """
+ if self._module is not None:
+ return self._module
+ self._module = rv = self.make_module()
+ return rv
+
+ def get_corresponding_lineno(self, lineno):
+ """Return the source line number of a line number in the
+ generated bytecode as they are not in sync.
+ """
+ for template_line, code_line in reversed(self.debug_info):
+ if code_line <= lineno:
+ return template_line
+ return 1
+
+ @property
+ def is_up_to_date(self):
+ """If this variable is `False` there is a newer version available."""
+ if self._uptodate is None:
+ return True
+ return self._uptodate()
+
+ @property
+ def debug_info(self):
+ """The debug info mapping."""
+ return [tuple(imap(int, x.split('='))) for x in
+ self._debug_info.split('&')]
+
+ def __repr__(self):
+ if self.name is None:
+ name = 'memory:%x' % id(self)
+ else:
+ name = repr(self.name)
+ return '<%s %s>' % (self.__class__.__name__, name)
+
+
+@implements_to_string
+class TemplateModule(object):
+ """Represents an imported template. All the exported names of the
+ template are available as attributes on this object. Additionally
+ converting it into an unicode- or bytestrings renders the contents.
+ """
+
+ def __init__(self, template, context):
+ self._body_stream = list(template.root_render_func(context))
+ self.__dict__.update(context.get_exported())
+ self.__name__ = template.name
+
+ def __html__(self):
+ return Markup(concat(self._body_stream))
+
+ def __str__(self):
+ return concat(self._body_stream)
+
+ def __repr__(self):
+ if self.__name__ is None:
+ name = 'memory:%x' % id(self)
+ else:
+ name = repr(self.__name__)
+ return '<%s %s>' % (self.__class__.__name__, name)
+
+
+class TemplateExpression(object):
+ """The :meth:`jinja2.Environment.compile_expression` method returns an
+ instance of this object. It encapsulates the expression-like access
+ to the template with an expression it wraps.
+ """
+
+ def __init__(self, template, undefined_to_none):
+ self._template = template
+ self._undefined_to_none = undefined_to_none
+
+ def __call__(self, *args, **kwargs):
+ context = self._template.new_context(dict(*args, **kwargs))
+ consume(self._template.root_render_func(context))
+ rv = context.vars['result']
+ if self._undefined_to_none and isinstance(rv, Undefined):
+ rv = None
+ return rv
+
+
+@implements_iterator
+class TemplateStream(object):
+ """A template stream works pretty much like an ordinary python generator
+ but it can buffer multiple items to reduce the number of total iterations.
+ Per default the output is unbuffered which means that for every unbuffered
+ instruction in the template one unicode string is yielded.
+
+ If buffering is enabled with a buffer size of 5, five items are combined
+ into a new unicode string. This is mainly useful if you are streaming
+ big templates to a client via WSGI which flushes after each iteration.
+ """
+
+ def __init__(self, gen):
+ self._gen = gen
+ self.disable_buffering()
+
+ def dump(self, fp, encoding=None, errors='strict'):
+ """Dump the complete stream into a file or file-like object.
+ Per default unicode strings are written, if you want to encode
+ before writing specify an `encoding`.
+
+ Example usage::
+
+ Template('Hello {{ name }}!').stream(name='foo').dump('hello.html')
+ """
+ close = False
+ if isinstance(fp, string_types):
+ if encoding is None:
+ encoding = 'utf-8'
+ fp = open(fp, 'wb')
+ close = True
+ try:
+ if encoding is not None:
+ iterable = (x.encode(encoding, errors) for x in self)
+ else:
+ iterable = self
+ if hasattr(fp, 'writelines'):
+ fp.writelines(iterable)
+ else:
+ for item in iterable:
+ fp.write(item)
+ finally:
+ if close:
+ fp.close()
+
+ def disable_buffering(self):
+ """Disable the output buffering."""
+ self._next = get_next(self._gen)
+ self.buffered = False
+
+ def enable_buffering(self, size=5):
+ """Enable buffering. Buffer `size` items before yielding them."""
+ if size <= 1:
+ raise ValueError('buffer size too small')
+
+ def generator(next):
+ buf = []
+ c_size = 0
+ push = buf.append
+
+ while 1:
+ try:
+ while c_size < size:
+ c = next()
+ push(c)
+ if c:
+ c_size += 1
+ except StopIteration:
+ if not c_size:
+ return
+ yield concat(buf)
+ del buf[:]
+ c_size = 0
+
+ self.buffered = True
+ self._next = get_next(generator(get_next(self._gen)))
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ return self._next()
+
+
+# hook in default template class. if anyone reads this comment: ignore that
+# it's possible to use custom templates ;-)
+Environment.template_class = Template
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/exceptions.py b/deps/v8_inspector/deps/jinja2/jinja2/exceptions.py
new file mode 100644
index 0000000000..c9df6dc7c2
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/exceptions.py
@@ -0,0 +1,146 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.exceptions
+ ~~~~~~~~~~~~~~~~~
+
+ Jinja exceptions.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+from jinja2._compat import imap, text_type, PY2, implements_to_string
+
+
+class TemplateError(Exception):
+ """Baseclass for all template errors."""
+
+ if PY2:
+ def __init__(self, message=None):
+ if message is not None:
+ message = text_type(message).encode('utf-8')
+ Exception.__init__(self, message)
+
+ @property
+ def message(self):
+ if self.args:
+ message = self.args[0]
+ if message is not None:
+ return message.decode('utf-8', 'replace')
+
+ def __unicode__(self):
+ return self.message or u''
+ else:
+ def __init__(self, message=None):
+ Exception.__init__(self, message)
+
+ @property
+ def message(self):
+ if self.args:
+ message = self.args[0]
+ if message is not None:
+ return message
+
+
+@implements_to_string
+class TemplateNotFound(IOError, LookupError, TemplateError):
+ """Raised if a template does not exist."""
+
+ # looks weird, but removes the warning descriptor that just
+ # bogusly warns us about message being deprecated
+ message = None
+
+ def __init__(self, name, message=None):
+ IOError.__init__(self)
+ if message is None:
+ message = name
+ self.message = message
+ self.name = name
+ self.templates = [name]
+
+ def __str__(self):
+ return self.message
+
+
+class TemplatesNotFound(TemplateNotFound):
+ """Like :class:`TemplateNotFound` but raised if multiple templates
+ are selected. This is a subclass of :class:`TemplateNotFound`
+ exception, so just catching the base exception will catch both.
+
+ .. versionadded:: 2.2
+ """
+
+ def __init__(self, names=(), message=None):
+ if message is None:
+ message = u'none of the templates given were found: ' + \
+ u', '.join(imap(text_type, names))
+ TemplateNotFound.__init__(self, names and names[-1] or None, message)
+ self.templates = list(names)
+
+
+@implements_to_string
+class TemplateSyntaxError(TemplateError):
+ """Raised to tell the user that there is a problem with the template."""
+
+ def __init__(self, message, lineno, name=None, filename=None):
+ TemplateError.__init__(self, message)
+ self.lineno = lineno
+ self.name = name
+ self.filename = filename
+ self.source = None
+
+ # this is set to True if the debug.translate_syntax_error
+ # function translated the syntax error into a new traceback
+ self.translated = False
+
+ def __str__(self):
+ # for translated errors we only return the message
+ if self.translated:
+ return self.message
+
+ # otherwise attach some stuff
+ location = 'line %d' % self.lineno
+ name = self.filename or self.name
+ if name:
+ location = 'File "%s", %s' % (name, location)
+ lines = [self.message, ' ' + location]
+
+ # if the source is set, add the line to the output
+ if self.source is not None:
+ try:
+ line = self.source.splitlines()[self.lineno - 1]
+ except IndexError:
+ line = None
+ if line:
+ lines.append(' ' + line.strip())
+
+ return u'\n'.join(lines)
+
+
+class TemplateAssertionError(TemplateSyntaxError):
+ """Like a template syntax error, but covers cases where something in the
+ template caused an error at compile time that wasn't necessarily caused
+ by a syntax error. However it's a direct subclass of
+ :exc:`TemplateSyntaxError` and has the same attributes.
+ """
+
+
+class TemplateRuntimeError(TemplateError):
+ """A generic runtime error in the template engine. Under some situations
+ Jinja may raise this exception.
+ """
+
+
+class UndefinedError(TemplateRuntimeError):
+ """Raised if a template tries to operate on :class:`Undefined`."""
+
+
+class SecurityError(TemplateRuntimeError):
+ """Raised if a template tries to do something insecure if the
+ sandbox is enabled.
+ """
+
+
+class FilterArgumentError(TemplateRuntimeError):
+ """This error is raised if a filter was called with inappropriate
+ arguments
+ """
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/ext.py b/deps/v8_inspector/deps/jinja2/jinja2/ext.py
new file mode 100644
index 0000000000..562ab506ff
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/ext.py
@@ -0,0 +1,636 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.ext
+ ~~~~~~~~~~
+
+ Jinja extensions allow to add custom tags similar to the way django custom
+ tags work. By default two example extensions exist: an i18n and a cache
+ extension.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD.
+"""
+from jinja2 import nodes
+from jinja2.defaults import BLOCK_START_STRING, \
+ BLOCK_END_STRING, VARIABLE_START_STRING, VARIABLE_END_STRING, \
+ COMMENT_START_STRING, COMMENT_END_STRING, LINE_STATEMENT_PREFIX, \
+ LINE_COMMENT_PREFIX, TRIM_BLOCKS, NEWLINE_SEQUENCE, \
+ KEEP_TRAILING_NEWLINE, LSTRIP_BLOCKS
+from jinja2.environment import Environment
+from jinja2.runtime import concat
+from jinja2.exceptions import TemplateAssertionError, TemplateSyntaxError
+from jinja2.utils import contextfunction, import_string, Markup
+from jinja2._compat import with_metaclass, string_types, iteritems
+
+
+# the only real useful gettext functions for a Jinja template. Note
+# that ugettext must be assigned to gettext as Jinja doesn't support
+# non unicode strings.
+GETTEXT_FUNCTIONS = ('_', 'gettext', 'ngettext')
+
+
+class ExtensionRegistry(type):
+ """Gives the extension an unique identifier."""
+
+ def __new__(cls, name, bases, d):
+ rv = type.__new__(cls, name, bases, d)
+ rv.identifier = rv.__module__ + '.' + rv.__name__
+ return rv
+
+
+class Extension(with_metaclass(ExtensionRegistry, object)):
+ """Extensions can be used to add extra functionality to the Jinja template
+ system at the parser level. Custom extensions are bound to an environment
+ but may not store environment specific data on `self`. The reason for
+ this is that an extension can be bound to another environment (for
+ overlays) by creating a copy and reassigning the `environment` attribute.
+
+ As extensions are created by the environment they cannot accept any
+ arguments for configuration. One may want to work around that by using
+ a factory function, but that is not possible as extensions are identified
+ by their import name. The correct way to configure the extension is
+ storing the configuration values on the environment. Because this way the
+ environment ends up acting as central configuration storage the
+ attributes may clash which is why extensions have to ensure that the names
+ they choose for configuration are not too generic. ``prefix`` for example
+ is a terrible name, ``fragment_cache_prefix`` on the other hand is a good
+ name as includes the name of the extension (fragment cache).
+ """
+
+ #: if this extension parses this is the list of tags it's listening to.
+ tags = set()
+
+ #: the priority of that extension. This is especially useful for
+ #: extensions that preprocess values. A lower value means higher
+ #: priority.
+ #:
+ #: .. versionadded:: 2.4
+ priority = 100
+
+ def __init__(self, environment):
+ self.environment = environment
+
+ def bind(self, environment):
+ """Create a copy of this extension bound to another environment."""
+ rv = object.__new__(self.__class__)
+ rv.__dict__.update(self.__dict__)
+ rv.environment = environment
+ return rv
+
+ def preprocess(self, source, name, filename=None):
+ """This method is called before the actual lexing and can be used to
+ preprocess the source. The `filename` is optional. The return value
+ must be the preprocessed source.
+ """
+ return source
+
+ def filter_stream(self, stream):
+ """It's passed a :class:`~jinja2.lexer.TokenStream` that can be used
+ to filter tokens returned. This method has to return an iterable of
+ :class:`~jinja2.lexer.Token`\s, but it doesn't have to return a
+ :class:`~jinja2.lexer.TokenStream`.
+
+ In the `ext` folder of the Jinja2 source distribution there is a file
+ called `inlinegettext.py` which implements a filter that utilizes this
+ method.
+ """
+ return stream
+
+ def parse(self, parser):
+ """If any of the :attr:`tags` matched this method is called with the
+ parser as first argument. The token the parser stream is pointing at
+ is the name token that matched. This method has to return one or a
+ list of multiple nodes.
+ """
+ raise NotImplementedError()
+
+ def attr(self, name, lineno=None):
+ """Return an attribute node for the current extension. This is useful
+ to pass constants on extensions to generated template code.
+
+ ::
+
+ self.attr('_my_attribute', lineno=lineno)
+ """
+ return nodes.ExtensionAttribute(self.identifier, name, lineno=lineno)
+
+ def call_method(self, name, args=None, kwargs=None, dyn_args=None,
+ dyn_kwargs=None, lineno=None):
+ """Call a method of the extension. This is a shortcut for
+ :meth:`attr` + :class:`jinja2.nodes.Call`.
+ """
+ if args is None:
+ args = []
+ if kwargs is None:
+ kwargs = []
+ return nodes.Call(self.attr(name, lineno=lineno), args, kwargs,
+ dyn_args, dyn_kwargs, lineno=lineno)
+
+
+@contextfunction
+def _gettext_alias(__context, *args, **kwargs):
+ return __context.call(__context.resolve('gettext'), *args, **kwargs)
+
+
+def _make_new_gettext(func):
+ @contextfunction
+ def gettext(__context, __string, **variables):
+ rv = __context.call(func, __string)
+ if __context.eval_ctx.autoescape:
+ rv = Markup(rv)
+ return rv % variables
+ return gettext
+
+
+def _make_new_ngettext(func):
+ @contextfunction
+ def ngettext(__context, __singular, __plural, __num, **variables):
+ variables.setdefault('num', __num)
+ rv = __context.call(func, __singular, __plural, __num)
+ if __context.eval_ctx.autoescape:
+ rv = Markup(rv)
+ return rv % variables
+ return ngettext
+
+
+class InternationalizationExtension(Extension):
+ """This extension adds gettext support to Jinja2."""
+ tags = set(['trans'])
+
+ # TODO: the i18n extension is currently reevaluating values in a few
+ # situations. Take this example:
+ # {% trans count=something() %}{{ count }} foo{% pluralize
+ # %}{{ count }} fooss{% endtrans %}
+ # something is called twice here. One time for the gettext value and
+ # the other time for the n-parameter of the ngettext function.
+
+ def __init__(self, environment):
+ Extension.__init__(self, environment)
+ environment.globals['_'] = _gettext_alias
+ environment.extend(
+ install_gettext_translations=self._install,
+ install_null_translations=self._install_null,
+ install_gettext_callables=self._install_callables,
+ uninstall_gettext_translations=self._uninstall,
+ extract_translations=self._extract,
+ newstyle_gettext=False
+ )
+
+ def _install(self, translations, newstyle=None):
+ gettext = getattr(translations, 'ugettext', None)
+ if gettext is None:
+ gettext = translations.gettext
+ ngettext = getattr(translations, 'ungettext', None)
+ if ngettext is None:
+ ngettext = translations.ngettext
+ self._install_callables(gettext, ngettext, newstyle)
+
+ def _install_null(self, newstyle=None):
+ self._install_callables(
+ lambda x: x,
+ lambda s, p, n: (n != 1 and (p,) or (s,))[0],
+ newstyle
+ )
+
+ def _install_callables(self, gettext, ngettext, newstyle=None):
+ if newstyle is not None:
+ self.environment.newstyle_gettext = newstyle
+ if self.environment.newstyle_gettext:
+ gettext = _make_new_gettext(gettext)
+ ngettext = _make_new_ngettext(ngettext)
+ self.environment.globals.update(
+ gettext=gettext,
+ ngettext=ngettext
+ )
+
+ def _uninstall(self, translations):
+ for key in 'gettext', 'ngettext':
+ self.environment.globals.pop(key, None)
+
+ def _extract(self, source, gettext_functions=GETTEXT_FUNCTIONS):
+ if isinstance(source, string_types):
+ source = self.environment.parse(source)
+ return extract_from_ast(source, gettext_functions)
+
+ def parse(self, parser):
+ """Parse a translatable tag."""
+ lineno = next(parser.stream).lineno
+ num_called_num = False
+
+ # find all the variables referenced. Additionally a variable can be
+ # defined in the body of the trans block too, but this is checked at
+ # a later state.
+ plural_expr = None
+ plural_expr_assignment = None
+ variables = {}
+ while parser.stream.current.type != 'block_end':
+ if variables:
+ parser.stream.expect('comma')
+
+ # skip colon for python compatibility
+ if parser.stream.skip_if('colon'):
+ break
+
+ name = parser.stream.expect('name')
+ if name.value in variables:
+ parser.fail('translatable variable %r defined twice.' %
+ name.value, name.lineno,
+ exc=TemplateAssertionError)
+
+ # expressions
+ if parser.stream.current.type == 'assign':
+ next(parser.stream)
+ variables[name.value] = var = parser.parse_expression()
+ else:
+ variables[name.value] = var = nodes.Name(name.value, 'load')
+
+ if plural_expr is None:
+ if isinstance(var, nodes.Call):
+ plural_expr = nodes.Name('_trans', 'load')
+ variables[name.value] = plural_expr
+ plural_expr_assignment = nodes.Assign(
+ nodes.Name('_trans', 'store'), var)
+ else:
+ plural_expr = var
+ num_called_num = name.value == 'num'
+
+ parser.stream.expect('block_end')
+
+ plural = plural_names = None
+ have_plural = False
+ referenced = set()
+
+ # now parse until endtrans or pluralize
+ singular_names, singular = self._parse_block(parser, True)
+ if singular_names:
+ referenced.update(singular_names)
+ if plural_expr is None:
+ plural_expr = nodes.Name(singular_names[0], 'load')
+ num_called_num = singular_names[0] == 'num'
+
+ # if we have a pluralize block, we parse that too
+ if parser.stream.current.test('name:pluralize'):
+ have_plural = True
+ next(parser.stream)
+ if parser.stream.current.type != 'block_end':
+ name = parser.stream.expect('name')
+ if name.value not in variables:
+ parser.fail('unknown variable %r for pluralization' %
+ name.value, name.lineno,
+ exc=TemplateAssertionError)
+ plural_expr = variables[name.value]
+ num_called_num = name.value == 'num'
+ parser.stream.expect('block_end')
+ plural_names, plural = self._parse_block(parser, False)
+ next(parser.stream)
+ referenced.update(plural_names)
+ else:
+ next(parser.stream)
+
+ # register free names as simple name expressions
+ for var in referenced:
+ if var not in variables:
+ variables[var] = nodes.Name(var, 'load')
+
+ if not have_plural:
+ plural_expr = None
+ elif plural_expr is None:
+ parser.fail('pluralize without variables', lineno)
+
+ node = self._make_node(singular, plural, variables, plural_expr,
+ bool(referenced),
+ num_called_num and have_plural)
+ node.set_lineno(lineno)
+ if plural_expr_assignment is not None:
+ return [plural_expr_assignment, node]
+ else:
+ return node
+
+ def _parse_block(self, parser, allow_pluralize):
+ """Parse until the next block tag with a given name."""
+ referenced = []
+ buf = []
+ while 1:
+ if parser.stream.current.type == 'data':
+ buf.append(parser.stream.current.value.replace('%', '%%'))
+ next(parser.stream)
+ elif parser.stream.current.type == 'variable_begin':
+ next(parser.stream)
+ name = parser.stream.expect('name').value
+ referenced.append(name)
+ buf.append('%%(%s)s' % name)
+ parser.stream.expect('variable_end')
+ elif parser.stream.current.type == 'block_begin':
+ next(parser.stream)
+ if parser.stream.current.test('name:endtrans'):
+ break
+ elif parser.stream.current.test('name:pluralize'):
+ if allow_pluralize:
+ break
+ parser.fail('a translatable section can have only one '
+ 'pluralize section')
+ parser.fail('control structures in translatable sections are '
+ 'not allowed')
+ elif parser.stream.eos:
+ parser.fail('unclosed translation block')
+ else:
+ assert False, 'internal parser error'
+
+ return referenced, concat(buf)
+
+ def _make_node(self, singular, plural, variables, plural_expr,
+ vars_referenced, num_called_num):
+ """Generates a useful node from the data provided."""
+ # no variables referenced? no need to escape for old style
+ # gettext invocations only if there are vars.
+ if not vars_referenced and not self.environment.newstyle_gettext:
+ singular = singular.replace('%%', '%')
+ if plural:
+ plural = plural.replace('%%', '%')
+
+ # singular only:
+ if plural_expr is None:
+ gettext = nodes.Name('gettext', 'load')
+ node = nodes.Call(gettext, [nodes.Const(singular)],
+ [], None, None)
+
+ # singular and plural
+ else:
+ ngettext = nodes.Name('ngettext', 'load')
+ node = nodes.Call(ngettext, [
+ nodes.Const(singular),
+ nodes.Const(plural),
+ plural_expr
+ ], [], None, None)
+
+ # in case newstyle gettext is used, the method is powerful
+ # enough to handle the variable expansion and autoescape
+ # handling itself
+ if self.environment.newstyle_gettext:
+ for key, value in iteritems(variables):
+ # the function adds that later anyways in case num was
+ # called num, so just skip it.
+ if num_called_num and key == 'num':
+ continue
+ node.kwargs.append(nodes.Keyword(key, value))
+
+ # otherwise do that here
+ else:
+ # mark the return value as safe if we are in an
+ # environment with autoescaping turned on
+ node = nodes.MarkSafeIfAutoescape(node)
+ if variables:
+ node = nodes.Mod(node, nodes.Dict([
+ nodes.Pair(nodes.Const(key), value)
+ for key, value in variables.items()
+ ]))
+ return nodes.Output([node])
+
+
+class ExprStmtExtension(Extension):
+ """Adds a `do` tag to Jinja2 that works like the print statement just
+ that it doesn't print the return value.
+ """
+ tags = set(['do'])
+
+ def parse(self, parser):
+ node = nodes.ExprStmt(lineno=next(parser.stream).lineno)
+ node.node = parser.parse_tuple()
+ return node
+
+
+class LoopControlExtension(Extension):
+ """Adds break and continue to the template engine."""
+ tags = set(['break', 'continue'])
+
+ def parse(self, parser):
+ token = next(parser.stream)
+ if token.value == 'break':
+ return nodes.Break(lineno=token.lineno)
+ return nodes.Continue(lineno=token.lineno)
+
+
+class WithExtension(Extension):
+ """Adds support for a django-like with block."""
+ tags = set(['with'])
+
+ def parse(self, parser):
+ node = nodes.Scope(lineno=next(parser.stream).lineno)
+ assignments = []
+ while parser.stream.current.type != 'block_end':
+ lineno = parser.stream.current.lineno
+ if assignments:
+ parser.stream.expect('comma')
+ target = parser.parse_assign_target()
+ parser.stream.expect('assign')
+ expr = parser.parse_expression()
+ assignments.append(nodes.Assign(target, expr, lineno=lineno))
+ node.body = assignments + \
+ list(parser.parse_statements(('name:endwith',),
+ drop_needle=True))
+ return node
+
+
+class AutoEscapeExtension(Extension):
+ """Changes auto escape rules for a scope."""
+ tags = set(['autoescape'])
+
+ def parse(self, parser):
+ node = nodes.ScopedEvalContextModifier(lineno=next(parser.stream).lineno)
+ node.options = [
+ nodes.Keyword('autoescape', parser.parse_expression())
+ ]
+ node.body = parser.parse_statements(('name:endautoescape',),
+ drop_needle=True)
+ return nodes.Scope([node])
+
+
+def extract_from_ast(node, gettext_functions=GETTEXT_FUNCTIONS,
+ babel_style=True):
+ """Extract localizable strings from the given template node. Per
+ default this function returns matches in babel style that means non string
+ parameters as well as keyword arguments are returned as `None`. This
+ allows Babel to figure out what you really meant if you are using
+ gettext functions that allow keyword arguments for placeholder expansion.
+ If you don't want that behavior set the `babel_style` parameter to `False`
+ which causes only strings to be returned and parameters are always stored
+ in tuples. As a consequence invalid gettext calls (calls without a single
+ string parameter or string parameters after non-string parameters) are
+ skipped.
+
+ This example explains the behavior:
+
+ >>> from jinja2 import Environment
+ >>> env = Environment()
+ >>> node = env.parse('{{ (_("foo"), _(), ngettext("foo", "bar", 42)) }}')
+ >>> list(extract_from_ast(node))
+ [(1, '_', 'foo'), (1, '_', ()), (1, 'ngettext', ('foo', 'bar', None))]
+ >>> list(extract_from_ast(node, babel_style=False))
+ [(1, '_', ('foo',)), (1, 'ngettext', ('foo', 'bar'))]
+
+ For every string found this function yields a ``(lineno, function,
+ message)`` tuple, where:
+
+ * ``lineno`` is the number of the line on which the string was found,
+ * ``function`` is the name of the ``gettext`` function used (if the
+ string was extracted from embedded Python code), and
+ * ``message`` is the string itself (a ``unicode`` object, or a tuple
+ of ``unicode`` objects for functions with multiple string arguments).
+
+ This extraction function operates on the AST and is because of that unable
+ to extract any comments. For comment support you have to use the babel
+ extraction interface or extract comments yourself.
+ """
+ for node in node.find_all(nodes.Call):
+ if not isinstance(node.node, nodes.Name) or \
+ node.node.name not in gettext_functions:
+ continue
+
+ strings = []
+ for arg in node.args:
+ if isinstance(arg, nodes.Const) and \
+ isinstance(arg.value, string_types):
+ strings.append(arg.value)
+ else:
+ strings.append(None)
+
+ for arg in node.kwargs:
+ strings.append(None)
+ if node.dyn_args is not None:
+ strings.append(None)
+ if node.dyn_kwargs is not None:
+ strings.append(None)
+
+ if not babel_style:
+ strings = tuple(x for x in strings if x is not None)
+ if not strings:
+ continue
+ else:
+ if len(strings) == 1:
+ strings = strings[0]
+ else:
+ strings = tuple(strings)
+ yield node.lineno, node.node.name, strings
+
+
+class _CommentFinder(object):
+ """Helper class to find comments in a token stream. Can only
+ find comments for gettext calls forwards. Once the comment
+ from line 4 is found, a comment for line 1 will not return a
+ usable value.
+ """
+
+ def __init__(self, tokens, comment_tags):
+ self.tokens = tokens
+ self.comment_tags = comment_tags
+ self.offset = 0
+ self.last_lineno = 0
+
+ def find_backwards(self, offset):
+ try:
+ for _, token_type, token_value in \
+ reversed(self.tokens[self.offset:offset]):
+ if token_type in ('comment', 'linecomment'):
+ try:
+ prefix, comment = token_value.split(None, 1)
+ except ValueError:
+ continue
+ if prefix in self.comment_tags:
+ return [comment.rstrip()]
+ return []
+ finally:
+ self.offset = offset
+
+ def find_comments(self, lineno):
+ if not self.comment_tags or self.last_lineno > lineno:
+ return []
+ for idx, (token_lineno, _, _) in enumerate(self.tokens[self.offset:]):
+ if token_lineno > lineno:
+ return self.find_backwards(self.offset + idx)
+ return self.find_backwards(len(self.tokens))
+
+
+def babel_extract(fileobj, keywords, comment_tags, options):
+ """Babel extraction method for Jinja templates.
+
+ .. versionchanged:: 2.3
+ Basic support for translation comments was added. If `comment_tags`
+ is now set to a list of keywords for extraction, the extractor will
+ try to find the best preceeding comment that begins with one of the
+ keywords. For best results, make sure to not have more than one
+ gettext call in one line of code and the matching comment in the
+ same line or the line before.
+
+ .. versionchanged:: 2.5.1
+ The `newstyle_gettext` flag can be set to `True` to enable newstyle
+ gettext calls.
+
+ .. versionchanged:: 2.7
+ A `silent` option can now be provided. If set to `False` template
+ syntax errors are propagated instead of being ignored.
+
+ :param fileobj: the file-like object the messages should be extracted from
+ :param keywords: a list of keywords (i.e. function names) that should be
+ recognized as translation functions
+ :param comment_tags: a list of translator tags to search for and include
+ in the results.
+ :param options: a dictionary of additional options (optional)
+ :return: an iterator over ``(lineno, funcname, message, comments)`` tuples.
+ (comments will be empty currently)
+ """
+ extensions = set()
+ for extension in options.get('extensions', '').split(','):
+ extension = extension.strip()
+ if not extension:
+ continue
+ extensions.add(import_string(extension))
+ if InternationalizationExtension not in extensions:
+ extensions.add(InternationalizationExtension)
+
+ def getbool(options, key, default=False):
+ return options.get(key, str(default)).lower() in \
+ ('1', 'on', 'yes', 'true')
+
+ silent = getbool(options, 'silent', True)
+ environment = Environment(
+ options.get('block_start_string', BLOCK_START_STRING),
+ options.get('block_end_string', BLOCK_END_STRING),
+ options.get('variable_start_string', VARIABLE_START_STRING),
+ options.get('variable_end_string', VARIABLE_END_STRING),
+ options.get('comment_start_string', COMMENT_START_STRING),
+ options.get('comment_end_string', COMMENT_END_STRING),
+ options.get('line_statement_prefix') or LINE_STATEMENT_PREFIX,
+ options.get('line_comment_prefix') or LINE_COMMENT_PREFIX,
+ getbool(options, 'trim_blocks', TRIM_BLOCKS),
+ getbool(options, 'lstrip_blocks', LSTRIP_BLOCKS),
+ NEWLINE_SEQUENCE,
+ getbool(options, 'keep_trailing_newline', KEEP_TRAILING_NEWLINE),
+ frozenset(extensions),
+ cache_size=0,
+ auto_reload=False
+ )
+
+ if getbool(options, 'newstyle_gettext'):
+ environment.newstyle_gettext = True
+
+ source = fileobj.read().decode(options.get('encoding', 'utf-8'))
+ try:
+ node = environment.parse(source)
+ tokens = list(environment.lex(environment.preprocess(source)))
+ except TemplateSyntaxError as e:
+ if not silent:
+ raise
+ # skip templates with syntax errors
+ return
+
+ finder = _CommentFinder(tokens, comment_tags)
+ for lineno, func, message in extract_from_ast(node, keywords):
+ yield lineno, func, message, finder.find_comments(lineno)
+
+
+#: nicer import names
+i18n = InternationalizationExtension
+do = ExprStmtExtension
+loopcontrols = LoopControlExtension
+with_ = WithExtension
+autoescape = AutoEscapeExtension
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/filters.py b/deps/v8_inspector/deps/jinja2/jinja2/filters.py
new file mode 100644
index 0000000000..cd89f6ffef
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/filters.py
@@ -0,0 +1,996 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.filters
+ ~~~~~~~~~~~~~~
+
+ Bundled jinja filters.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import re
+import math
+
+from random import choice
+from operator import itemgetter
+from itertools import groupby
+from jinja2.utils import Markup, escape, pformat, urlize, soft_unicode, \
+ unicode_urlencode
+from jinja2.runtime import Undefined
+from jinja2.exceptions import FilterArgumentError
+from jinja2._compat import imap, string_types, text_type, iteritems
+
+
+_word_re = re.compile(r'\w+(?u)')
+
+
+def contextfilter(f):
+ """Decorator for marking context dependent filters. The current
+ :class:`Context` will be passed as first argument.
+ """
+ f.contextfilter = True
+ return f
+
+
+def evalcontextfilter(f):
+ """Decorator for marking eval-context dependent filters. An eval
+ context object is passed as first argument. For more information
+ about the eval context, see :ref:`eval-context`.
+
+ .. versionadded:: 2.4
+ """
+ f.evalcontextfilter = True
+ return f
+
+
+def environmentfilter(f):
+ """Decorator for marking environment dependent filters. The current
+ :class:`Environment` is passed to the filter as first argument.
+ """
+ f.environmentfilter = True
+ return f
+
+
+def make_attrgetter(environment, attribute):
+ """Returns a callable that looks up the given attribute from a
+ passed object with the rules of the environment. Dots are allowed
+ to access attributes of attributes. Integer parts in paths are
+ looked up as integers.
+ """
+ if not isinstance(attribute, string_types) \
+ or ('.' not in attribute and not attribute.isdigit()):
+ return lambda x: environment.getitem(x, attribute)
+ attribute = attribute.split('.')
+ def attrgetter(item):
+ for part in attribute:
+ if part.isdigit():
+ part = int(part)
+ item = environment.getitem(item, part)
+ return item
+ return attrgetter
+
+
+def do_forceescape(value):
+ """Enforce HTML escaping. This will probably double escape variables."""
+ if hasattr(value, '__html__'):
+ value = value.__html__()
+ return escape(text_type(value))
+
+
+def do_urlencode(value):
+ """Escape strings for use in URLs (uses UTF-8 encoding). It accepts both
+ dictionaries and regular strings as well as pairwise iterables.
+
+ .. versionadded:: 2.7
+ """
+ itemiter = None
+ if isinstance(value, dict):
+ itemiter = iteritems(value)
+ elif not isinstance(value, string_types):
+ try:
+ itemiter = iter(value)
+ except TypeError:
+ pass
+ if itemiter is None:
+ return unicode_urlencode(value)
+ return u'&'.join(unicode_urlencode(k) + '=' +
+ unicode_urlencode(v, for_qs=True)
+ for k, v in itemiter)
+
+
+@evalcontextfilter
+def do_replace(eval_ctx, s, old, new, count=None):
+ """Return a copy of the value with all occurrences of a substring
+ replaced with a new one. The first argument is the substring
+ that should be replaced, the second is the replacement string.
+ If the optional third argument ``count`` is given, only the first
+ ``count`` occurrences are replaced:
+
+ .. sourcecode:: jinja
+
+ {{ "Hello World"|replace("Hello", "Goodbye") }}
+ -> Goodbye World
+
+ {{ "aaaaargh"|replace("a", "d'oh, ", 2) }}
+ -> d'oh, d'oh, aaargh
+ """
+ if count is None:
+ count = -1
+ if not eval_ctx.autoescape:
+ return text_type(s).replace(text_type(old), text_type(new), count)
+ if hasattr(old, '__html__') or hasattr(new, '__html__') and \
+ not hasattr(s, '__html__'):
+ s = escape(s)
+ else:
+ s = soft_unicode(s)
+ return s.replace(soft_unicode(old), soft_unicode(new), count)
+
+
+def do_upper(s):
+ """Convert a value to uppercase."""
+ return soft_unicode(s).upper()
+
+
+def do_lower(s):
+ """Convert a value to lowercase."""
+ return soft_unicode(s).lower()
+
+
+@evalcontextfilter
+def do_xmlattr(_eval_ctx, d, autospace=True):
+ """Create an SGML/XML attribute string based on the items in a dict.
+ All values that are neither `none` nor `undefined` are automatically
+ escaped:
+
+ .. sourcecode:: html+jinja
+
+ <ul{{ {'class': 'my_list', 'missing': none,
+ 'id': 'list-%d'|format(variable)}|xmlattr }}>
+ ...
+ </ul>
+
+ Results in something like this:
+
+ .. sourcecode:: html
+
+ <ul class="my_list" id="list-42">
+ ...
+ </ul>
+
+ As you can see it automatically prepends a space in front of the item
+ if the filter returned something unless the second parameter is false.
+ """
+ rv = u' '.join(
+ u'%s="%s"' % (escape(key), escape(value))
+ for key, value in iteritems(d)
+ if value is not None and not isinstance(value, Undefined)
+ )
+ if autospace and rv:
+ rv = u' ' + rv
+ if _eval_ctx.autoescape:
+ rv = Markup(rv)
+ return rv
+
+
+def do_capitalize(s):
+ """Capitalize a value. The first character will be uppercase, all others
+ lowercase.
+ """
+ return soft_unicode(s).capitalize()
+
+
+def do_title(s):
+ """Return a titlecased version of the value. I.e. words will start with
+ uppercase letters, all remaining characters are lowercase.
+ """
+ rv = []
+ for item in re.compile(r'([-\s]+)(?u)').split(soft_unicode(s)):
+ if not item:
+ continue
+ rv.append(item[0].upper() + item[1:].lower())
+ return ''.join(rv)
+
+
+def do_dictsort(value, case_sensitive=False, by='key'):
+ """Sort a dict and yield (key, value) pairs. Because python dicts are
+ unsorted you may want to use this function to order them by either
+ key or value:
+
+ .. sourcecode:: jinja
+
+ {% for item in mydict|dictsort %}
+ sort the dict by key, case insensitive
+
+ {% for item in mydict|dictsort(true) %}
+ sort the dict by key, case sensitive
+
+ {% for item in mydict|dictsort(false, 'value') %}
+ sort the dict by value, case insensitive
+ """
+ if by == 'key':
+ pos = 0
+ elif by == 'value':
+ pos = 1
+ else:
+ raise FilterArgumentError('You can only sort by either '
+ '"key" or "value"')
+ def sort_func(item):
+ value = item[pos]
+ if isinstance(value, string_types) and not case_sensitive:
+ value = value.lower()
+ return value
+
+ return sorted(value.items(), key=sort_func)
+
+
+@environmentfilter
+def do_sort(environment, value, reverse=False, case_sensitive=False,
+ attribute=None):
+ """Sort an iterable. Per default it sorts ascending, if you pass it
+ true as first argument it will reverse the sorting.
+
+ If the iterable is made of strings the third parameter can be used to
+ control the case sensitiveness of the comparison which is disabled by
+ default.
+
+ .. sourcecode:: jinja
+
+ {% for item in iterable|sort %}
+ ...
+ {% endfor %}
+
+ It is also possible to sort by an attribute (for example to sort
+ by the date of an object) by specifying the `attribute` parameter:
+
+ .. sourcecode:: jinja
+
+ {% for item in iterable|sort(attribute='date') %}
+ ...
+ {% endfor %}
+
+ .. versionchanged:: 2.6
+ The `attribute` parameter was added.
+ """
+ if not case_sensitive:
+ def sort_func(item):
+ if isinstance(item, string_types):
+ item = item.lower()
+ return item
+ else:
+ sort_func = None
+ if attribute is not None:
+ getter = make_attrgetter(environment, attribute)
+ def sort_func(item, processor=sort_func or (lambda x: x)):
+ return processor(getter(item))
+ return sorted(value, key=sort_func, reverse=reverse)
+
+
+def do_default(value, default_value=u'', boolean=False):
+ """If the value is undefined it will return the passed default value,
+ otherwise the value of the variable:
+
+ .. sourcecode:: jinja
+
+ {{ my_variable|default('my_variable is not defined') }}
+
+ This will output the value of ``my_variable`` if the variable was
+ defined, otherwise ``'my_variable is not defined'``. If you want
+ to use default with variables that evaluate to false you have to
+ set the second parameter to `true`:
+
+ .. sourcecode:: jinja
+
+ {{ ''|default('the string was empty', true) }}
+ """
+ if isinstance(value, Undefined) or (boolean and not value):
+ return default_value
+ return value
+
+
+@evalcontextfilter
+def do_join(eval_ctx, value, d=u'', attribute=None):
+ """Return a string which is the concatenation of the strings in the
+ sequence. The separator between elements is an empty string per
+ default, you can define it with the optional parameter:
+
+ .. sourcecode:: jinja
+
+ {{ [1, 2, 3]|join('|') }}
+ -> 1|2|3
+
+ {{ [1, 2, 3]|join }}
+ -> 123
+
+ It is also possible to join certain attributes of an object:
+
+ .. sourcecode:: jinja
+
+ {{ users|join(', ', attribute='username') }}
+
+ .. versionadded:: 2.6
+ The `attribute` parameter was added.
+ """
+ if attribute is not None:
+ value = imap(make_attrgetter(eval_ctx.environment, attribute), value)
+
+ # no automatic escaping? joining is a lot eaiser then
+ if not eval_ctx.autoescape:
+ return text_type(d).join(imap(text_type, value))
+
+ # if the delimiter doesn't have an html representation we check
+ # if any of the items has. If yes we do a coercion to Markup
+ if not hasattr(d, '__html__'):
+ value = list(value)
+ do_escape = False
+ for idx, item in enumerate(value):
+ if hasattr(item, '__html__'):
+ do_escape = True
+ else:
+ value[idx] = text_type(item)
+ if do_escape:
+ d = escape(d)
+ else:
+ d = text_type(d)
+ return d.join(value)
+
+ # no html involved, to normal joining
+ return soft_unicode(d).join(imap(soft_unicode, value))
+
+
+def do_center(value, width=80):
+ """Centers the value in a field of a given width."""
+ return text_type(value).center(width)
+
+
+@environmentfilter
+def do_first(environment, seq):
+ """Return the first item of a sequence."""
+ try:
+ return next(iter(seq))
+ except StopIteration:
+ return environment.undefined('No first item, sequence was empty.')
+
+
+@environmentfilter
+def do_last(environment, seq):
+ """Return the last item of a sequence."""
+ try:
+ return next(iter(reversed(seq)))
+ except StopIteration:
+ return environment.undefined('No last item, sequence was empty.')
+
+
+@environmentfilter
+def do_random(environment, seq):
+ """Return a random item from the sequence."""
+ try:
+ return choice(seq)
+ except IndexError:
+ return environment.undefined('No random item, sequence was empty.')
+
+
+def do_filesizeformat(value, binary=False):
+ """Format the value like a 'human-readable' file size (i.e. 13 kB,
+ 4.1 MB, 102 Bytes, etc). Per default decimal prefixes are used (Mega,
+ Giga, etc.), if the second parameter is set to `True` the binary
+ prefixes are used (Mebi, Gibi).
+ """
+ bytes = float(value)
+ base = binary and 1024 or 1000
+ prefixes = [
+ (binary and 'KiB' or 'kB'),
+ (binary and 'MiB' or 'MB'),
+ (binary and 'GiB' or 'GB'),
+ (binary and 'TiB' or 'TB'),
+ (binary and 'PiB' or 'PB'),
+ (binary and 'EiB' or 'EB'),
+ (binary and 'ZiB' or 'ZB'),
+ (binary and 'YiB' or 'YB')
+ ]
+ if bytes == 1:
+ return '1 Byte'
+ elif bytes < base:
+ return '%d Bytes' % bytes
+ else:
+ for i, prefix in enumerate(prefixes):
+ unit = base ** (i + 2)
+ if bytes < unit:
+ return '%.1f %s' % ((base * bytes / unit), prefix)
+ return '%.1f %s' % ((base * bytes / unit), prefix)
+
+
+def do_pprint(value, verbose=False):
+ """Pretty print a variable. Useful for debugging.
+
+ With Jinja 1.2 onwards you can pass it a parameter. If this parameter
+ is truthy the output will be more verbose (this requires `pretty`)
+ """
+ return pformat(value, verbose=verbose)
+
+
+@evalcontextfilter
+def do_urlize(eval_ctx, value, trim_url_limit=None, nofollow=False,
+ target=None):
+ """Converts URLs in plain text into clickable links.
+
+ If you pass the filter an additional integer it will shorten the urls
+ to that number. Also a third argument exists that makes the urls
+ "nofollow":
+
+ .. sourcecode:: jinja
+
+ {{ mytext|urlize(40, true) }}
+ links are shortened to 40 chars and defined with rel="nofollow"
+
+ If *target* is specified, the ``target`` attribute will be added to the
+ ``<a>`` tag:
+
+ .. sourcecode:: jinja
+
+ {{ mytext|urlize(40, target='_blank') }}
+
+ .. versionchanged:: 2.8+
+ The *target* parameter was added.
+ """
+ rv = urlize(value, trim_url_limit, nofollow, target)
+ if eval_ctx.autoescape:
+ rv = Markup(rv)
+ return rv
+
+
+def do_indent(s, width=4, indentfirst=False):
+ """Return a copy of the passed string, each line indented by
+ 4 spaces. The first line is not indented. If you want to
+ change the number of spaces or indent the first line too
+ you can pass additional parameters to the filter:
+
+ .. sourcecode:: jinja
+
+ {{ mytext|indent(2, true) }}
+ indent by two spaces and indent the first line too.
+ """
+ indention = u' ' * width
+ rv = (u'\n' + indention).join(s.splitlines())
+ if indentfirst:
+ rv = indention + rv
+ return rv
+
+
+def do_truncate(s, length=255, killwords=False, end='...'):
+ """Return a truncated copy of the string. The length is specified
+ with the first parameter which defaults to ``255``. If the second
+ parameter is ``true`` the filter will cut the text at length. Otherwise
+ it will discard the last word. If the text was in fact
+ truncated it will append an ellipsis sign (``"..."``). If you want a
+ different ellipsis sign than ``"..."`` you can specify it using the
+ third parameter.
+
+ .. sourcecode:: jinja
+
+ {{ "foo bar baz"|truncate(9) }}
+ -> "foo ..."
+ {{ "foo bar baz"|truncate(9, True) }}
+ -> "foo ba..."
+
+ """
+ if len(s) <= length:
+ return s
+ elif killwords:
+ return s[:length - len(end)] + end
+
+ result = s[:length - len(end)].rsplit(' ', 1)[0]
+ if len(result) < length:
+ result += ' '
+ return result + end
+
+
+@environmentfilter
+def do_wordwrap(environment, s, width=79, break_long_words=True,
+ wrapstring=None):
+ """
+ Return a copy of the string passed to the filter wrapped after
+ ``79`` characters. You can override this default using the first
+ parameter. If you set the second parameter to `false` Jinja will not
+ split words apart if they are longer than `width`. By default, the newlines
+ will be the default newlines for the environment, but this can be changed
+ using the wrapstring keyword argument.
+
+ .. versionadded:: 2.7
+ Added support for the `wrapstring` parameter.
+ """
+ if not wrapstring:
+ wrapstring = environment.newline_sequence
+ import textwrap
+ return wrapstring.join(textwrap.wrap(s, width=width, expand_tabs=False,
+ replace_whitespace=False,
+ break_long_words=break_long_words))
+
+
+def do_wordcount(s):
+ """Count the words in that string."""
+ return len(_word_re.findall(s))
+
+
+def do_int(value, default=0, base=10):
+ """Convert the value into an integer. If the
+ conversion doesn't work it will return ``0``. You can
+ override this default using the first parameter. You
+ can also override the default base (10) in the second
+ parameter, which handles input with prefixes such as
+ 0b, 0o and 0x for bases 2, 8 and 16 respectively.
+ """
+ try:
+ return int(value, base)
+ except (TypeError, ValueError):
+ # this quirk is necessary so that "42.23"|int gives 42.
+ try:
+ return int(float(value))
+ except (TypeError, ValueError):
+ return default
+
+
+def do_float(value, default=0.0):
+ """Convert the value into a floating point number. If the
+ conversion doesn't work it will return ``0.0``. You can
+ override this default using the first parameter.
+ """
+ try:
+ return float(value)
+ except (TypeError, ValueError):
+ return default
+
+
+def do_format(value, *args, **kwargs):
+ """
+ Apply python string formatting on an object:
+
+ .. sourcecode:: jinja
+
+ {{ "%s - %s"|format("Hello?", "Foo!") }}
+ -> Hello? - Foo!
+ """
+ if args and kwargs:
+ raise FilterArgumentError('can\'t handle positional and keyword '
+ 'arguments at the same time')
+ return soft_unicode(value) % (kwargs or args)
+
+
+def do_trim(value):
+ """Strip leading and trailing whitespace."""
+ return soft_unicode(value).strip()
+
+
+def do_striptags(value):
+ """Strip SGML/XML tags and replace adjacent whitespace by one space.
+ """
+ if hasattr(value, '__html__'):
+ value = value.__html__()
+ return Markup(text_type(value)).striptags()
+
+
+def do_slice(value, slices, fill_with=None):
+ """Slice an iterator and return a list of lists containing
+ those items. Useful if you want to create a div containing
+ three ul tags that represent columns:
+
+ .. sourcecode:: html+jinja
+
+ <div class="columwrapper">
+ {%- for column in items|slice(3) %}
+ <ul class="column-{{ loop.index }}">
+ {%- for item in column %}
+ <li>{{ item }}</li>
+ {%- endfor %}
+ </ul>
+ {%- endfor %}
+ </div>
+
+ If you pass it a second argument it's used to fill missing
+ values on the last iteration.
+ """
+ seq = list(value)
+ length = len(seq)
+ items_per_slice = length // slices
+ slices_with_extra = length % slices
+ offset = 0
+ for slice_number in range(slices):
+ start = offset + slice_number * items_per_slice
+ if slice_number < slices_with_extra:
+ offset += 1
+ end = offset + (slice_number + 1) * items_per_slice
+ tmp = seq[start:end]
+ if fill_with is not None and slice_number >= slices_with_extra:
+ tmp.append(fill_with)
+ yield tmp
+
+
+def do_batch(value, linecount, fill_with=None):
+ """
+ A filter that batches items. It works pretty much like `slice`
+ just the other way round. It returns a list of lists with the
+ given number of items. If you provide a second parameter this
+ is used to fill up missing items. See this example:
+
+ .. sourcecode:: html+jinja
+
+ <table>
+ {%- for row in items|batch(3, '&nbsp;') %}
+ <tr>
+ {%- for column in row %}
+ <td>{{ column }}</td>
+ {%- endfor %}
+ </tr>
+ {%- endfor %}
+ </table>
+ """
+ tmp = []
+ for item in value:
+ if len(tmp) == linecount:
+ yield tmp
+ tmp = []
+ tmp.append(item)
+ if tmp:
+ if fill_with is not None and len(tmp) < linecount:
+ tmp += [fill_with] * (linecount - len(tmp))
+ yield tmp
+
+
+def do_round(value, precision=0, method='common'):
+ """Round the number to a given precision. The first
+ parameter specifies the precision (default is ``0``), the
+ second the rounding method:
+
+ - ``'common'`` rounds either up or down
+ - ``'ceil'`` always rounds up
+ - ``'floor'`` always rounds down
+
+ If you don't specify a method ``'common'`` is used.
+
+ .. sourcecode:: jinja
+
+ {{ 42.55|round }}
+ -> 43.0
+ {{ 42.55|round(1, 'floor') }}
+ -> 42.5
+
+ Note that even if rounded to 0 precision, a float is returned. If
+ you need a real integer, pipe it through `int`:
+
+ .. sourcecode:: jinja
+
+ {{ 42.55|round|int }}
+ -> 43
+ """
+ if not method in ('common', 'ceil', 'floor'):
+ raise FilterArgumentError('method must be common, ceil or floor')
+ if method == 'common':
+ return round(value, precision)
+ func = getattr(math, method)
+ return func(value * (10 ** precision)) / (10 ** precision)
+
+
+@environmentfilter
+def do_groupby(environment, value, attribute):
+ """Group a sequence of objects by a common attribute.
+
+ If you for example have a list of dicts or objects that represent persons
+ with `gender`, `first_name` and `last_name` attributes and you want to
+ group all users by genders you can do something like the following
+ snippet:
+
+ .. sourcecode:: html+jinja
+
+ <ul>
+ {% for group in persons|groupby('gender') %}
+ <li>{{ group.grouper }}<ul>
+ {% for person in group.list %}
+ <li>{{ person.first_name }} {{ person.last_name }}</li>
+ {% endfor %}</ul></li>
+ {% endfor %}
+ </ul>
+
+ Additionally it's possible to use tuple unpacking for the grouper and
+ list:
+
+ .. sourcecode:: html+jinja
+
+ <ul>
+ {% for grouper, list in persons|groupby('gender') %}
+ ...
+ {% endfor %}
+ </ul>
+
+ As you can see the item we're grouping by is stored in the `grouper`
+ attribute and the `list` contains all the objects that have this grouper
+ in common.
+
+ .. versionchanged:: 2.6
+ It's now possible to use dotted notation to group by the child
+ attribute of another attribute.
+ """
+ expr = make_attrgetter(environment, attribute)
+ return sorted(map(_GroupTuple, groupby(sorted(value, key=expr), expr)))
+
+
+class _GroupTuple(tuple):
+ __slots__ = ()
+ grouper = property(itemgetter(0))
+ list = property(itemgetter(1))
+
+ def __new__(cls, xxx_todo_changeme):
+ (key, value) = xxx_todo_changeme
+ return tuple.__new__(cls, (key, list(value)))
+
+
+@environmentfilter
+def do_sum(environment, iterable, attribute=None, start=0):
+ """Returns the sum of a sequence of numbers plus the value of parameter
+ 'start' (which defaults to 0). When the sequence is empty it returns
+ start.
+
+ It is also possible to sum up only certain attributes:
+
+ .. sourcecode:: jinja
+
+ Total: {{ items|sum(attribute='price') }}
+
+ .. versionchanged:: 2.6
+ The `attribute` parameter was added to allow suming up over
+ attributes. Also the `start` parameter was moved on to the right.
+ """
+ if attribute is not None:
+ iterable = imap(make_attrgetter(environment, attribute), iterable)
+ return sum(iterable, start)
+
+
+def do_list(value):
+ """Convert the value into a list. If it was a string the returned list
+ will be a list of characters.
+ """
+ return list(value)
+
+
+def do_mark_safe(value):
+ """Mark the value as safe which means that in an environment with automatic
+ escaping enabled this variable will not be escaped.
+ """
+ return Markup(value)
+
+
+def do_mark_unsafe(value):
+ """Mark a value as unsafe. This is the reverse operation for :func:`safe`."""
+ return text_type(value)
+
+
+def do_reverse(value):
+ """Reverse the object or return an iterator that iterates over it the other
+ way round.
+ """
+ if isinstance(value, string_types):
+ return value[::-1]
+ try:
+ return reversed(value)
+ except TypeError:
+ try:
+ rv = list(value)
+ rv.reverse()
+ return rv
+ except TypeError:
+ raise FilterArgumentError('argument must be iterable')
+
+
+@environmentfilter
+def do_attr(environment, obj, name):
+ """Get an attribute of an object. ``foo|attr("bar")`` works like
+ ``foo.bar`` just that always an attribute is returned and items are not
+ looked up.
+
+ See :ref:`Notes on subscriptions <notes-on-subscriptions>` for more details.
+ """
+ try:
+ name = str(name)
+ except UnicodeError:
+ pass
+ else:
+ try:
+ value = getattr(obj, name)
+ except AttributeError:
+ pass
+ else:
+ if environment.sandboxed and not \
+ environment.is_safe_attribute(obj, name, value):
+ return environment.unsafe_undefined(obj, name)
+ return value
+ return environment.undefined(obj=obj, name=name)
+
+
+@contextfilter
+def do_map(*args, **kwargs):
+ """Applies a filter on a sequence of objects or looks up an attribute.
+ This is useful when dealing with lists of objects but you are really
+ only interested in a certain value of it.
+
+ The basic usage is mapping on an attribute. Imagine you have a list
+ of users but you are only interested in a list of usernames:
+
+ .. sourcecode:: jinja
+
+ Users on this page: {{ users|map(attribute='username')|join(', ') }}
+
+ Alternatively you can let it invoke a filter by passing the name of the
+ filter and the arguments afterwards. A good example would be applying a
+ text conversion filter on a sequence:
+
+ .. sourcecode:: jinja
+
+ Users on this page: {{ titles|map('lower')|join(', ') }}
+
+ .. versionadded:: 2.7
+ """
+ context = args[0]
+ seq = args[1]
+
+ if len(args) == 2 and 'attribute' in kwargs:
+ attribute = kwargs.pop('attribute')
+ if kwargs:
+ raise FilterArgumentError('Unexpected keyword argument %r' %
+ next(iter(kwargs)))
+ func = make_attrgetter(context.environment, attribute)
+ else:
+ try:
+ name = args[2]
+ args = args[3:]
+ except LookupError:
+ raise FilterArgumentError('map requires a filter argument')
+ func = lambda item: context.environment.call_filter(
+ name, item, args, kwargs, context=context)
+
+ if seq:
+ for item in seq:
+ yield func(item)
+
+
+@contextfilter
+def do_select(*args, **kwargs):
+ """Filters a sequence of objects by applying a test to the object and only
+ selecting the ones with the test succeeding.
+
+ Example usage:
+
+ .. sourcecode:: jinja
+
+ {{ numbers|select("odd") }}
+ {{ numbers|select("odd") }}
+
+ .. versionadded:: 2.7
+ """
+ return _select_or_reject(args, kwargs, lambda x: x, False)
+
+
+@contextfilter
+def do_reject(*args, **kwargs):
+ """Filters a sequence of objects by applying a test to the object and
+ rejecting the ones with the test succeeding.
+
+ Example usage:
+
+ .. sourcecode:: jinja
+
+ {{ numbers|reject("odd") }}
+
+ .. versionadded:: 2.7
+ """
+ return _select_or_reject(args, kwargs, lambda x: not x, False)
+
+
+@contextfilter
+def do_selectattr(*args, **kwargs):
+ """Filters a sequence of objects by applying a test to an attribute of an
+ object and only selecting the ones with the test succeeding.
+
+ Example usage:
+
+ .. sourcecode:: jinja
+
+ {{ users|selectattr("is_active") }}
+ {{ users|selectattr("email", "none") }}
+
+ .. versionadded:: 2.7
+ """
+ return _select_or_reject(args, kwargs, lambda x: x, True)
+
+
+@contextfilter
+def do_rejectattr(*args, **kwargs):
+ """Filters a sequence of objects by applying a test to an attribute of an
+ object or the attribute and rejecting the ones with the test succeeding.
+
+ .. sourcecode:: jinja
+
+ {{ users|rejectattr("is_active") }}
+ {{ users|rejectattr("email", "none") }}
+
+ .. versionadded:: 2.7
+ """
+ return _select_or_reject(args, kwargs, lambda x: not x, True)
+
+
+def _select_or_reject(args, kwargs, modfunc, lookup_attr):
+ context = args[0]
+ seq = args[1]
+ if lookup_attr:
+ try:
+ attr = args[2]
+ except LookupError:
+ raise FilterArgumentError('Missing parameter for attribute name')
+ transfunc = make_attrgetter(context.environment, attr)
+ off = 1
+ else:
+ off = 0
+ transfunc = lambda x: x
+
+ try:
+ name = args[2 + off]
+ args = args[3 + off:]
+ func = lambda item: context.environment.call_test(
+ name, item, args, kwargs)
+ except LookupError:
+ func = bool
+
+ if seq:
+ for item in seq:
+ if modfunc(func(transfunc(item))):
+ yield item
+
+
+FILTERS = {
+ 'abs': abs,
+ 'attr': do_attr,
+ 'batch': do_batch,
+ 'capitalize': do_capitalize,
+ 'center': do_center,
+ 'count': len,
+ 'd': do_default,
+ 'default': do_default,
+ 'dictsort': do_dictsort,
+ 'e': escape,
+ 'escape': escape,
+ 'filesizeformat': do_filesizeformat,
+ 'first': do_first,
+ 'float': do_float,
+ 'forceescape': do_forceescape,
+ 'format': do_format,
+ 'groupby': do_groupby,
+ 'indent': do_indent,
+ 'int': do_int,
+ 'join': do_join,
+ 'last': do_last,
+ 'length': len,
+ 'list': do_list,
+ 'lower': do_lower,
+ 'map': do_map,
+ 'pprint': do_pprint,
+ 'random': do_random,
+ 'reject': do_reject,
+ 'rejectattr': do_rejectattr,
+ 'replace': do_replace,
+ 'reverse': do_reverse,
+ 'round': do_round,
+ 'safe': do_mark_safe,
+ 'select': do_select,
+ 'selectattr': do_selectattr,
+ 'slice': do_slice,
+ 'sort': do_sort,
+ 'string': soft_unicode,
+ 'striptags': do_striptags,
+ 'sum': do_sum,
+ 'title': do_title,
+ 'trim': do_trim,
+ 'truncate': do_truncate,
+ 'upper': do_upper,
+ 'urlencode': do_urlencode,
+ 'urlize': do_urlize,
+ 'wordcount': do_wordcount,
+ 'wordwrap': do_wordwrap,
+ 'xmlattr': do_xmlattr,
+}
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/lexer.py b/deps/v8_inspector/deps/jinja2/jinja2/lexer.py
new file mode 100644
index 0000000000..c8dac214ed
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/lexer.py
@@ -0,0 +1,734 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.lexer
+ ~~~~~~~~~~~~
+
+ This module implements a Jinja / Python combination lexer. The
+ `Lexer` class provided by this module is used to do some preprocessing
+ for Jinja.
+
+ On the one hand it filters out invalid operators like the bitshift
+ operators we don't allow in templates. On the other hand it separates
+ template code and python code in expressions.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import re
+
+from operator import itemgetter
+from collections import deque
+from jinja2.exceptions import TemplateSyntaxError
+from jinja2.utils import LRUCache
+from jinja2._compat import iteritems, implements_iterator, text_type, \
+ intern, PY2
+
+
+# cache for the lexers. Exists in order to be able to have multiple
+# environments with the same lexer
+_lexer_cache = LRUCache(50)
+
+# static regular expressions
+whitespace_re = re.compile(r'\s+', re.U)
+string_re = re.compile(r"('([^'\\]*(?:\\.[^'\\]*)*)'"
+ r'|"([^"\\]*(?:\\.[^"\\]*)*)")', re.S)
+integer_re = re.compile(r'\d+')
+
+# we use the unicode identifier rule if this python version is able
+# to handle unicode identifiers, otherwise the standard ASCII one.
+try:
+ compile('föö', '<unknown>', 'eval')
+except SyntaxError:
+ name_re = re.compile(r'\b[a-zA-Z_][a-zA-Z0-9_]*\b')
+else:
+ from jinja2 import _stringdefs
+ name_re = re.compile(r'[%s][%s]*' % (_stringdefs.xid_start,
+ _stringdefs.xid_continue))
+
+float_re = re.compile(r'(?<!\.)\d+\.\d+')
+newline_re = re.compile(r'(\r\n|\r|\n)')
+
+# internal the tokens and keep references to them
+TOKEN_ADD = intern('add')
+TOKEN_ASSIGN = intern('assign')
+TOKEN_COLON = intern('colon')
+TOKEN_COMMA = intern('comma')
+TOKEN_DIV = intern('div')
+TOKEN_DOT = intern('dot')
+TOKEN_EQ = intern('eq')
+TOKEN_FLOORDIV = intern('floordiv')
+TOKEN_GT = intern('gt')
+TOKEN_GTEQ = intern('gteq')
+TOKEN_LBRACE = intern('lbrace')
+TOKEN_LBRACKET = intern('lbracket')
+TOKEN_LPAREN = intern('lparen')
+TOKEN_LT = intern('lt')
+TOKEN_LTEQ = intern('lteq')
+TOKEN_MOD = intern('mod')
+TOKEN_MUL = intern('mul')
+TOKEN_NE = intern('ne')
+TOKEN_PIPE = intern('pipe')
+TOKEN_POW = intern('pow')
+TOKEN_RBRACE = intern('rbrace')
+TOKEN_RBRACKET = intern('rbracket')
+TOKEN_RPAREN = intern('rparen')
+TOKEN_SEMICOLON = intern('semicolon')
+TOKEN_SUB = intern('sub')
+TOKEN_TILDE = intern('tilde')
+TOKEN_WHITESPACE = intern('whitespace')
+TOKEN_FLOAT = intern('float')
+TOKEN_INTEGER = intern('integer')
+TOKEN_NAME = intern('name')
+TOKEN_STRING = intern('string')
+TOKEN_OPERATOR = intern('operator')
+TOKEN_BLOCK_BEGIN = intern('block_begin')
+TOKEN_BLOCK_END = intern('block_end')
+TOKEN_VARIABLE_BEGIN = intern('variable_begin')
+TOKEN_VARIABLE_END = intern('variable_end')
+TOKEN_RAW_BEGIN = intern('raw_begin')
+TOKEN_RAW_END = intern('raw_end')
+TOKEN_COMMENT_BEGIN = intern('comment_begin')
+TOKEN_COMMENT_END = intern('comment_end')
+TOKEN_COMMENT = intern('comment')
+TOKEN_LINESTATEMENT_BEGIN = intern('linestatement_begin')
+TOKEN_LINESTATEMENT_END = intern('linestatement_end')
+TOKEN_LINECOMMENT_BEGIN = intern('linecomment_begin')
+TOKEN_LINECOMMENT_END = intern('linecomment_end')
+TOKEN_LINECOMMENT = intern('linecomment')
+TOKEN_DATA = intern('data')
+TOKEN_INITIAL = intern('initial')
+TOKEN_EOF = intern('eof')
+
+# bind operators to token types
+operators = {
+ '+': TOKEN_ADD,
+ '-': TOKEN_SUB,
+ '/': TOKEN_DIV,
+ '//': TOKEN_FLOORDIV,
+ '*': TOKEN_MUL,
+ '%': TOKEN_MOD,
+ '**': TOKEN_POW,
+ '~': TOKEN_TILDE,
+ '[': TOKEN_LBRACKET,
+ ']': TOKEN_RBRACKET,
+ '(': TOKEN_LPAREN,
+ ')': TOKEN_RPAREN,
+ '{': TOKEN_LBRACE,
+ '}': TOKEN_RBRACE,
+ '==': TOKEN_EQ,
+ '!=': TOKEN_NE,
+ '>': TOKEN_GT,
+ '>=': TOKEN_GTEQ,
+ '<': TOKEN_LT,
+ '<=': TOKEN_LTEQ,
+ '=': TOKEN_ASSIGN,
+ '.': TOKEN_DOT,
+ ':': TOKEN_COLON,
+ '|': TOKEN_PIPE,
+ ',': TOKEN_COMMA,
+ ';': TOKEN_SEMICOLON
+}
+
+reverse_operators = dict([(v, k) for k, v in iteritems(operators)])
+assert len(operators) == len(reverse_operators), 'operators dropped'
+operator_re = re.compile('(%s)' % '|'.join(re.escape(x) for x in
+ sorted(operators, key=lambda x: -len(x))))
+
+ignored_tokens = frozenset([TOKEN_COMMENT_BEGIN, TOKEN_COMMENT,
+ TOKEN_COMMENT_END, TOKEN_WHITESPACE,
+ TOKEN_LINECOMMENT_BEGIN, TOKEN_LINECOMMENT_END,
+ TOKEN_LINECOMMENT])
+ignore_if_empty = frozenset([TOKEN_WHITESPACE, TOKEN_DATA,
+ TOKEN_COMMENT, TOKEN_LINECOMMENT])
+
+
+def _describe_token_type(token_type):
+ if token_type in reverse_operators:
+ return reverse_operators[token_type]
+ return {
+ TOKEN_COMMENT_BEGIN: 'begin of comment',
+ TOKEN_COMMENT_END: 'end of comment',
+ TOKEN_COMMENT: 'comment',
+ TOKEN_LINECOMMENT: 'comment',
+ TOKEN_BLOCK_BEGIN: 'begin of statement block',
+ TOKEN_BLOCK_END: 'end of statement block',
+ TOKEN_VARIABLE_BEGIN: 'begin of print statement',
+ TOKEN_VARIABLE_END: 'end of print statement',
+ TOKEN_LINESTATEMENT_BEGIN: 'begin of line statement',
+ TOKEN_LINESTATEMENT_END: 'end of line statement',
+ TOKEN_DATA: 'template data / text',
+ TOKEN_EOF: 'end of template'
+ }.get(token_type, token_type)
+
+
+def describe_token(token):
+ """Returns a description of the token."""
+ if token.type == 'name':
+ return token.value
+ return _describe_token_type(token.type)
+
+
+def describe_token_expr(expr):
+ """Like `describe_token` but for token expressions."""
+ if ':' in expr:
+ type, value = expr.split(':', 1)
+ if type == 'name':
+ return value
+ else:
+ type = expr
+ return _describe_token_type(type)
+
+
+def count_newlines(value):
+ """Count the number of newline characters in the string. This is
+ useful for extensions that filter a stream.
+ """
+ return len(newline_re.findall(value))
+
+
+def compile_rules(environment):
+ """Compiles all the rules from the environment into a list of rules."""
+ e = re.escape
+ rules = [
+ (len(environment.comment_start_string), 'comment',
+ e(environment.comment_start_string)),
+ (len(environment.block_start_string), 'block',
+ e(environment.block_start_string)),
+ (len(environment.variable_start_string), 'variable',
+ e(environment.variable_start_string))
+ ]
+
+ if environment.line_statement_prefix is not None:
+ rules.append((len(environment.line_statement_prefix), 'linestatement',
+ r'^[ \t\v]*' + e(environment.line_statement_prefix)))
+ if environment.line_comment_prefix is not None:
+ rules.append((len(environment.line_comment_prefix), 'linecomment',
+ r'(?:^|(?<=\S))[^\S\r\n]*' +
+ e(environment.line_comment_prefix)))
+
+ return [x[1:] for x in sorted(rules, reverse=True)]
+
+
+class Failure(object):
+ """Class that raises a `TemplateSyntaxError` if called.
+ Used by the `Lexer` to specify known errors.
+ """
+
+ def __init__(self, message, cls=TemplateSyntaxError):
+ self.message = message
+ self.error_class = cls
+
+ def __call__(self, lineno, filename):
+ raise self.error_class(self.message, lineno, filename)
+
+
+class Token(tuple):
+ """Token class."""
+ __slots__ = ()
+ lineno, type, value = (property(itemgetter(x)) for x in range(3))
+
+ def __new__(cls, lineno, type, value):
+ return tuple.__new__(cls, (lineno, intern(str(type)), value))
+
+ def __str__(self):
+ if self.type in reverse_operators:
+ return reverse_operators[self.type]
+ elif self.type == 'name':
+ return self.value
+ return self.type
+
+ def test(self, expr):
+ """Test a token against a token expression. This can either be a
+ token type or ``'token_type:token_value'``. This can only test
+ against string values and types.
+ """
+ # here we do a regular string equality check as test_any is usually
+ # passed an iterable of not interned strings.
+ if self.type == expr:
+ return True
+ elif ':' in expr:
+ return expr.split(':', 1) == [self.type, self.value]
+ return False
+
+ def test_any(self, *iterable):
+ """Test against multiple token expressions."""
+ for expr in iterable:
+ if self.test(expr):
+ return True
+ return False
+
+ def __repr__(self):
+ return 'Token(%r, %r, %r)' % (
+ self.lineno,
+ self.type,
+ self.value
+ )
+
+
+@implements_iterator
+class TokenStreamIterator(object):
+ """The iterator for tokenstreams. Iterate over the stream
+ until the eof token is reached.
+ """
+
+ def __init__(self, stream):
+ self.stream = stream
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ token = self.stream.current
+ if token.type is TOKEN_EOF:
+ self.stream.close()
+ raise StopIteration()
+ next(self.stream)
+ return token
+
+
+@implements_iterator
+class TokenStream(object):
+ """A token stream is an iterable that yields :class:`Token`\s. The
+ parser however does not iterate over it but calls :meth:`next` to go
+ one token ahead. The current active token is stored as :attr:`current`.
+ """
+
+ def __init__(self, generator, name, filename):
+ self._iter = iter(generator)
+ self._pushed = deque()
+ self.name = name
+ self.filename = filename
+ self.closed = False
+ self.current = Token(1, TOKEN_INITIAL, '')
+ next(self)
+
+ def __iter__(self):
+ return TokenStreamIterator(self)
+
+ def __bool__(self):
+ return bool(self._pushed) or self.current.type is not TOKEN_EOF
+ __nonzero__ = __bool__ # py2
+
+ eos = property(lambda x: not x, doc="Are we at the end of the stream?")
+
+ def push(self, token):
+ """Push a token back to the stream."""
+ self._pushed.append(token)
+
+ def look(self):
+ """Look at the next token."""
+ old_token = next(self)
+ result = self.current
+ self.push(result)
+ self.current = old_token
+ return result
+
+ def skip(self, n=1):
+ """Got n tokens ahead."""
+ for x in range(n):
+ next(self)
+
+ def next_if(self, expr):
+ """Perform the token test and return the token if it matched.
+ Otherwise the return value is `None`.
+ """
+ if self.current.test(expr):
+ return next(self)
+
+ def skip_if(self, expr):
+ """Like :meth:`next_if` but only returns `True` or `False`."""
+ return self.next_if(expr) is not None
+
+ def __next__(self):
+ """Go one token ahead and return the old one"""
+ rv = self.current
+ if self._pushed:
+ self.current = self._pushed.popleft()
+ elif self.current.type is not TOKEN_EOF:
+ try:
+ self.current = next(self._iter)
+ except StopIteration:
+ self.close()
+ return rv
+
+ def close(self):
+ """Close the stream."""
+ self.current = Token(self.current.lineno, TOKEN_EOF, '')
+ self._iter = None
+ self.closed = True
+
+ def expect(self, expr):
+ """Expect a given token type and return it. This accepts the same
+ argument as :meth:`jinja2.lexer.Token.test`.
+ """
+ if not self.current.test(expr):
+ expr = describe_token_expr(expr)
+ if self.current.type is TOKEN_EOF:
+ raise TemplateSyntaxError('unexpected end of template, '
+ 'expected %r.' % expr,
+ self.current.lineno,
+ self.name, self.filename)
+ raise TemplateSyntaxError("expected token %r, got %r" %
+ (expr, describe_token(self.current)),
+ self.current.lineno,
+ self.name, self.filename)
+ try:
+ return self.current
+ finally:
+ next(self)
+
+
+def get_lexer(environment):
+ """Return a lexer which is probably cached."""
+ key = (environment.block_start_string,
+ environment.block_end_string,
+ environment.variable_start_string,
+ environment.variable_end_string,
+ environment.comment_start_string,
+ environment.comment_end_string,
+ environment.line_statement_prefix,
+ environment.line_comment_prefix,
+ environment.trim_blocks,
+ environment.lstrip_blocks,
+ environment.newline_sequence,
+ environment.keep_trailing_newline)
+ lexer = _lexer_cache.get(key)
+ if lexer is None:
+ lexer = Lexer(environment)
+ _lexer_cache[key] = lexer
+ return lexer
+
+
+class Lexer(object):
+ """Class that implements a lexer for a given environment. Automatically
+ created by the environment class, usually you don't have to do that.
+
+ Note that the lexer is not automatically bound to an environment.
+ Multiple environments can share the same lexer.
+ """
+
+ def __init__(self, environment):
+ # shortcuts
+ c = lambda x: re.compile(x, re.M | re.S)
+ e = re.escape
+
+ # lexing rules for tags
+ tag_rules = [
+ (whitespace_re, TOKEN_WHITESPACE, None),
+ (float_re, TOKEN_FLOAT, None),
+ (integer_re, TOKEN_INTEGER, None),
+ (name_re, TOKEN_NAME, None),
+ (string_re, TOKEN_STRING, None),
+ (operator_re, TOKEN_OPERATOR, None)
+ ]
+
+ # assemble the root lexing rule. because "|" is ungreedy
+ # we have to sort by length so that the lexer continues working
+ # as expected when we have parsing rules like <% for block and
+ # <%= for variables. (if someone wants asp like syntax)
+ # variables are just part of the rules if variable processing
+ # is required.
+ root_tag_rules = compile_rules(environment)
+
+ # block suffix if trimming is enabled
+ block_suffix_re = environment.trim_blocks and '\\n?' or ''
+
+ # strip leading spaces if lstrip_blocks is enabled
+ prefix_re = {}
+ if environment.lstrip_blocks:
+ # use '{%+' to manually disable lstrip_blocks behavior
+ no_lstrip_re = e('+')
+ # detect overlap between block and variable or comment strings
+ block_diff = c(r'^%s(.*)' % e(environment.block_start_string))
+ # make sure we don't mistake a block for a variable or a comment
+ m = block_diff.match(environment.comment_start_string)
+ no_lstrip_re += m and r'|%s' % e(m.group(1)) or ''
+ m = block_diff.match(environment.variable_start_string)
+ no_lstrip_re += m and r'|%s' % e(m.group(1)) or ''
+
+ # detect overlap between comment and variable strings
+ comment_diff = c(r'^%s(.*)' % e(environment.comment_start_string))
+ m = comment_diff.match(environment.variable_start_string)
+ no_variable_re = m and r'(?!%s)' % e(m.group(1)) or ''
+
+ lstrip_re = r'^[ \t]*'
+ block_prefix_re = r'%s%s(?!%s)|%s\+?' % (
+ lstrip_re,
+ e(environment.block_start_string),
+ no_lstrip_re,
+ e(environment.block_start_string),
+ )
+ comment_prefix_re = r'%s%s%s|%s\+?' % (
+ lstrip_re,
+ e(environment.comment_start_string),
+ no_variable_re,
+ e(environment.comment_start_string),
+ )
+ prefix_re['block'] = block_prefix_re
+ prefix_re['comment'] = comment_prefix_re
+ else:
+ block_prefix_re = '%s' % e(environment.block_start_string)
+
+ self.newline_sequence = environment.newline_sequence
+ self.keep_trailing_newline = environment.keep_trailing_newline
+
+ # global lexing rules
+ self.rules = {
+ 'root': [
+ # directives
+ (c('(.*?)(?:%s)' % '|'.join(
+ [r'(?P<raw_begin>(?:\s*%s\-|%s)\s*raw\s*(?:\-%s\s*|%s))' % (
+ e(environment.block_start_string),
+ block_prefix_re,
+ e(environment.block_end_string),
+ e(environment.block_end_string)
+ )] + [
+ r'(?P<%s_begin>\s*%s\-|%s)' % (n, r, prefix_re.get(n,r))
+ for n, r in root_tag_rules
+ ])), (TOKEN_DATA, '#bygroup'), '#bygroup'),
+ # data
+ (c('.+'), TOKEN_DATA, None)
+ ],
+ # comments
+ TOKEN_COMMENT_BEGIN: [
+ (c(r'(.*?)((?:\-%s\s*|%s)%s)' % (
+ e(environment.comment_end_string),
+ e(environment.comment_end_string),
+ block_suffix_re
+ )), (TOKEN_COMMENT, TOKEN_COMMENT_END), '#pop'),
+ (c('(.)'), (Failure('Missing end of comment tag'),), None)
+ ],
+ # blocks
+ TOKEN_BLOCK_BEGIN: [
+ (c('(?:\-%s\s*|%s)%s' % (
+ e(environment.block_end_string),
+ e(environment.block_end_string),
+ block_suffix_re
+ )), TOKEN_BLOCK_END, '#pop'),
+ ] + tag_rules,
+ # variables
+ TOKEN_VARIABLE_BEGIN: [
+ (c('\-%s\s*|%s' % (
+ e(environment.variable_end_string),
+ e(environment.variable_end_string)
+ )), TOKEN_VARIABLE_END, '#pop')
+ ] + tag_rules,
+ # raw block
+ TOKEN_RAW_BEGIN: [
+ (c('(.*?)((?:\s*%s\-|%s)\s*endraw\s*(?:\-%s\s*|%s%s))' % (
+ e(environment.block_start_string),
+ block_prefix_re,
+ e(environment.block_end_string),
+ e(environment.block_end_string),
+ block_suffix_re
+ )), (TOKEN_DATA, TOKEN_RAW_END), '#pop'),
+ (c('(.)'), (Failure('Missing end of raw directive'),), None)
+ ],
+ # line statements
+ TOKEN_LINESTATEMENT_BEGIN: [
+ (c(r'\s*(\n|$)'), TOKEN_LINESTATEMENT_END, '#pop')
+ ] + tag_rules,
+ # line comments
+ TOKEN_LINECOMMENT_BEGIN: [
+ (c(r'(.*?)()(?=\n|$)'), (TOKEN_LINECOMMENT,
+ TOKEN_LINECOMMENT_END), '#pop')
+ ]
+ }
+
+ def _normalize_newlines(self, value):
+ """Called for strings and template data to normalize it to unicode."""
+ return newline_re.sub(self.newline_sequence, value)
+
+ def tokenize(self, source, name=None, filename=None, state=None):
+ """Calls tokeniter + tokenize and wraps it in a token stream.
+ """
+ stream = self.tokeniter(source, name, filename, state)
+ return TokenStream(self.wrap(stream, name, filename), name, filename)
+
+ def wrap(self, stream, name=None, filename=None):
+ """This is called with the stream as returned by `tokenize` and wraps
+ every token in a :class:`Token` and converts the value.
+ """
+ for lineno, token, value in stream:
+ if token in ignored_tokens:
+ continue
+ elif token == 'linestatement_begin':
+ token = 'block_begin'
+ elif token == 'linestatement_end':
+ token = 'block_end'
+ # we are not interested in those tokens in the parser
+ elif token in ('raw_begin', 'raw_end'):
+ continue
+ elif token == 'data':
+ value = self._normalize_newlines(value)
+ elif token == 'keyword':
+ token = value
+ elif token == 'name':
+ value = str(value)
+ elif token == 'string':
+ # try to unescape string
+ try:
+ value = self._normalize_newlines(value[1:-1]) \
+ .encode('ascii', 'backslashreplace') \
+ .decode('unicode-escape')
+ except Exception as e:
+ msg = str(e).split(':')[-1].strip()
+ raise TemplateSyntaxError(msg, lineno, name, filename)
+ # if we can express it as bytestring (ascii only)
+ # we do that for support of semi broken APIs
+ # as datetime.datetime.strftime. On python 3 this
+ # call becomes a noop thanks to 2to3
+ if PY2:
+ try:
+ value = value.encode('ascii')
+ except UnicodeError:
+ pass
+ elif token == 'integer':
+ value = int(value)
+ elif token == 'float':
+ value = float(value)
+ elif token == 'operator':
+ token = operators[value]
+ yield Token(lineno, token, value)
+
+ def tokeniter(self, source, name, filename=None, state=None):
+ """This method tokenizes the text and returns the tokens in a
+ generator. Use this method if you just want to tokenize a template.
+ """
+ source = text_type(source)
+ lines = source.splitlines()
+ if self.keep_trailing_newline and source:
+ for newline in ('\r\n', '\r', '\n'):
+ if source.endswith(newline):
+ lines.append('')
+ break
+ source = '\n'.join(lines)
+ pos = 0
+ lineno = 1
+ stack = ['root']
+ if state is not None and state != 'root':
+ assert state in ('variable', 'block'), 'invalid state'
+ stack.append(state + '_begin')
+ else:
+ state = 'root'
+ statetokens = self.rules[stack[-1]]
+ source_length = len(source)
+
+ balancing_stack = []
+
+ while 1:
+ # tokenizer loop
+ for regex, tokens, new_state in statetokens:
+ m = regex.match(source, pos)
+ # if no match we try again with the next rule
+ if m is None:
+ continue
+
+ # we only match blocks and variables if braces / parentheses
+ # are balanced. continue parsing with the lower rule which
+ # is the operator rule. do this only if the end tags look
+ # like operators
+ if balancing_stack and \
+ tokens in ('variable_end', 'block_end',
+ 'linestatement_end'):
+ continue
+
+ # tuples support more options
+ if isinstance(tokens, tuple):
+ for idx, token in enumerate(tokens):
+ # failure group
+ if token.__class__ is Failure:
+ raise token(lineno, filename)
+ # bygroup is a bit more complex, in that case we
+ # yield for the current token the first named
+ # group that matched
+ elif token == '#bygroup':
+ for key, value in iteritems(m.groupdict()):
+ if value is not None:
+ yield lineno, key, value
+ lineno += value.count('\n')
+ break
+ else:
+ raise RuntimeError('%r wanted to resolve '
+ 'the token dynamically'
+ ' but no group matched'
+ % regex)
+ # normal group
+ else:
+ data = m.group(idx + 1)
+ if data or token not in ignore_if_empty:
+ yield lineno, token, data
+ lineno += data.count('\n')
+
+ # strings as token just are yielded as it.
+ else:
+ data = m.group()
+ # update brace/parentheses balance
+ if tokens == 'operator':
+ if data == '{':
+ balancing_stack.append('}')
+ elif data == '(':
+ balancing_stack.append(')')
+ elif data == '[':
+ balancing_stack.append(']')
+ elif data in ('}', ')', ']'):
+ if not balancing_stack:
+ raise TemplateSyntaxError('unexpected \'%s\'' %
+ data, lineno, name,
+ filename)
+ expected_op = balancing_stack.pop()
+ if expected_op != data:
+ raise TemplateSyntaxError('unexpected \'%s\', '
+ 'expected \'%s\'' %
+ (data, expected_op),
+ lineno, name,
+ filename)
+ # yield items
+ if data or tokens not in ignore_if_empty:
+ yield lineno, tokens, data
+ lineno += data.count('\n')
+
+ # fetch new position into new variable so that we can check
+ # if there is a internal parsing error which would result
+ # in an infinite loop
+ pos2 = m.end()
+
+ # handle state changes
+ if new_state is not None:
+ # remove the uppermost state
+ if new_state == '#pop':
+ stack.pop()
+ # resolve the new state by group checking
+ elif new_state == '#bygroup':
+ for key, value in iteritems(m.groupdict()):
+ if value is not None:
+ stack.append(key)
+ break
+ else:
+ raise RuntimeError('%r wanted to resolve the '
+ 'new state dynamically but'
+ ' no group matched' %
+ regex)
+ # direct state name given
+ else:
+ stack.append(new_state)
+ statetokens = self.rules[stack[-1]]
+ # we are still at the same position and no stack change.
+ # this means a loop without break condition, avoid that and
+ # raise error
+ elif pos2 == pos:
+ raise RuntimeError('%r yielded empty string without '
+ 'stack change' % regex)
+ # publish new function and start again
+ pos = pos2
+ break
+ # if loop terminated without break we haven't found a single match
+ # either we are at the end of the file or we have a problem
+ else:
+ # end of text
+ if pos >= source_length:
+ return
+ # something went wrong
+ raise TemplateSyntaxError('unexpected char %r at %d' %
+ (source[pos], pos), lineno,
+ name, filename)
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/loaders.py b/deps/v8_inspector/deps/jinja2/jinja2/loaders.py
new file mode 100644
index 0000000000..44aa3925a2
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/loaders.py
@@ -0,0 +1,481 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.loaders
+ ~~~~~~~~~~~~~~
+
+ Jinja loader classes.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import os
+import sys
+import weakref
+from types import ModuleType
+from os import path
+from hashlib import sha1
+from jinja2.exceptions import TemplateNotFound
+from jinja2.utils import open_if_exists, internalcode
+from jinja2._compat import string_types, iteritems
+
+
+def split_template_path(template):
+ """Split a path into segments and perform a sanity check. If it detects
+ '..' in the path it will raise a `TemplateNotFound` error.
+ """
+ pieces = []
+ for piece in template.split('/'):
+ if path.sep in piece \
+ or (path.altsep and path.altsep in piece) or \
+ piece == path.pardir:
+ raise TemplateNotFound(template)
+ elif piece and piece != '.':
+ pieces.append(piece)
+ return pieces
+
+
+class BaseLoader(object):
+ """Baseclass for all loaders. Subclass this and override `get_source` to
+ implement a custom loading mechanism. The environment provides a
+ `get_template` method that calls the loader's `load` method to get the
+ :class:`Template` object.
+
+ A very basic example for a loader that looks up templates on the file
+ system could look like this::
+
+ from jinja2 import BaseLoader, TemplateNotFound
+ from os.path import join, exists, getmtime
+
+ class MyLoader(BaseLoader):
+
+ def __init__(self, path):
+ self.path = path
+
+ def get_source(self, environment, template):
+ path = join(self.path, template)
+ if not exists(path):
+ raise TemplateNotFound(template)
+ mtime = getmtime(path)
+ with file(path) as f:
+ source = f.read().decode('utf-8')
+ return source, path, lambda: mtime == getmtime(path)
+ """
+
+ #: if set to `False` it indicates that the loader cannot provide access
+ #: to the source of templates.
+ #:
+ #: .. versionadded:: 2.4
+ has_source_access = True
+
+ def get_source(self, environment, template):
+ """Get the template source, filename and reload helper for a template.
+ It's passed the environment and template name and has to return a
+ tuple in the form ``(source, filename, uptodate)`` or raise a
+ `TemplateNotFound` error if it can't locate the template.
+
+ The source part of the returned tuple must be the source of the
+ template as unicode string or a ASCII bytestring. The filename should
+ be the name of the file on the filesystem if it was loaded from there,
+ otherwise `None`. The filename is used by python for the tracebacks
+ if no loader extension is used.
+
+ The last item in the tuple is the `uptodate` function. If auto
+ reloading is enabled it's always called to check if the template
+ changed. No arguments are passed so the function must store the
+ old state somewhere (for example in a closure). If it returns `False`
+ the template will be reloaded.
+ """
+ if not self.has_source_access:
+ raise RuntimeError('%s cannot provide access to the source' %
+ self.__class__.__name__)
+ raise TemplateNotFound(template)
+
+ def list_templates(self):
+ """Iterates over all templates. If the loader does not support that
+ it should raise a :exc:`TypeError` which is the default behavior.
+ """
+ raise TypeError('this loader cannot iterate over all templates')
+
+ @internalcode
+ def load(self, environment, name, globals=None):
+ """Loads a template. This method looks up the template in the cache
+ or loads one by calling :meth:`get_source`. Subclasses should not
+ override this method as loaders working on collections of other
+ loaders (such as :class:`PrefixLoader` or :class:`ChoiceLoader`)
+ will not call this method but `get_source` directly.
+ """
+ code = None
+ if globals is None:
+ globals = {}
+
+ # first we try to get the source for this template together
+ # with the filename and the uptodate function.
+ source, filename, uptodate = self.get_source(environment, name)
+
+ # try to load the code from the bytecode cache if there is a
+ # bytecode cache configured.
+ bcc = environment.bytecode_cache
+ if bcc is not None:
+ bucket = bcc.get_bucket(environment, name, filename, source)
+ code = bucket.code
+
+ # if we don't have code so far (not cached, no longer up to
+ # date) etc. we compile the template
+ if code is None:
+ code = environment.compile(source, name, filename)
+
+ # if the bytecode cache is available and the bucket doesn't
+ # have a code so far, we give the bucket the new code and put
+ # it back to the bytecode cache.
+ if bcc is not None and bucket.code is None:
+ bucket.code = code
+ bcc.set_bucket(bucket)
+
+ return environment.template_class.from_code(environment, code,
+ globals, uptodate)
+
+
+class FileSystemLoader(BaseLoader):
+ """Loads templates from the file system. This loader can find templates
+ in folders on the file system and is the preferred way to load them.
+
+ The loader takes the path to the templates as string, or if multiple
+ locations are wanted a list of them which is then looked up in the
+ given order::
+
+ >>> loader = FileSystemLoader('/path/to/templates')
+ >>> loader = FileSystemLoader(['/path/to/templates', '/other/path'])
+
+ Per default the template encoding is ``'utf-8'`` which can be changed
+ by setting the `encoding` parameter to something else.
+
+ To follow symbolic links, set the *followlinks* parameter to ``True``::
+
+ >>> loader = FileSystemLoader('/path/to/templates', followlinks=True)
+
+ .. versionchanged:: 2.8+
+ The *followlinks* parameter was added.
+ """
+
+ def __init__(self, searchpath, encoding='utf-8', followlinks=False):
+ if isinstance(searchpath, string_types):
+ searchpath = [searchpath]
+ self.searchpath = list(searchpath)
+ self.encoding = encoding
+ self.followlinks = followlinks
+
+ def get_source(self, environment, template):
+ pieces = split_template_path(template)
+ for searchpath in self.searchpath:
+ filename = path.join(searchpath, *pieces)
+ f = open_if_exists(filename)
+ if f is None:
+ continue
+ try:
+ contents = f.read().decode(self.encoding)
+ finally:
+ f.close()
+
+ mtime = path.getmtime(filename)
+
+ def uptodate():
+ try:
+ return path.getmtime(filename) == mtime
+ except OSError:
+ return False
+ return contents, filename, uptodate
+ raise TemplateNotFound(template)
+
+ def list_templates(self):
+ found = set()
+ for searchpath in self.searchpath:
+ walk_dir = os.walk(searchpath, followlinks=self.followlinks)
+ for dirpath, dirnames, filenames in walk_dir:
+ for filename in filenames:
+ template = os.path.join(dirpath, filename) \
+ [len(searchpath):].strip(os.path.sep) \
+ .replace(os.path.sep, '/')
+ if template[:2] == './':
+ template = template[2:]
+ if template not in found:
+ found.add(template)
+ return sorted(found)
+
+
+class PackageLoader(BaseLoader):
+ """Load templates from python eggs or packages. It is constructed with
+ the name of the python package and the path to the templates in that
+ package::
+
+ loader = PackageLoader('mypackage', 'views')
+
+ If the package path is not given, ``'templates'`` is assumed.
+
+ Per default the template encoding is ``'utf-8'`` which can be changed
+ by setting the `encoding` parameter to something else. Due to the nature
+ of eggs it's only possible to reload templates if the package was loaded
+ from the file system and not a zip file.
+ """
+
+ def __init__(self, package_name, package_path='templates',
+ encoding='utf-8'):
+ from pkg_resources import DefaultProvider, ResourceManager, \
+ get_provider
+ provider = get_provider(package_name)
+ self.encoding = encoding
+ self.manager = ResourceManager()
+ self.filesystem_bound = isinstance(provider, DefaultProvider)
+ self.provider = provider
+ self.package_path = package_path
+
+ def get_source(self, environment, template):
+ pieces = split_template_path(template)
+ p = '/'.join((self.package_path,) + tuple(pieces))
+ if not self.provider.has_resource(p):
+ raise TemplateNotFound(template)
+
+ filename = uptodate = None
+ if self.filesystem_bound:
+ filename = self.provider.get_resource_filename(self.manager, p)
+ mtime = path.getmtime(filename)
+ def uptodate():
+ try:
+ return path.getmtime(filename) == mtime
+ except OSError:
+ return False
+
+ source = self.provider.get_resource_string(self.manager, p)
+ return source.decode(self.encoding), filename, uptodate
+
+ def list_templates(self):
+ path = self.package_path
+ if path[:2] == './':
+ path = path[2:]
+ elif path == '.':
+ path = ''
+ offset = len(path)
+ results = []
+ def _walk(path):
+ for filename in self.provider.resource_listdir(path):
+ fullname = path + '/' + filename
+ if self.provider.resource_isdir(fullname):
+ _walk(fullname)
+ else:
+ results.append(fullname[offset:].lstrip('/'))
+ _walk(path)
+ results.sort()
+ return results
+
+
+class DictLoader(BaseLoader):
+ """Loads a template from a python dict. It's passed a dict of unicode
+ strings bound to template names. This loader is useful for unittesting:
+
+ >>> loader = DictLoader({'index.html': 'source here'})
+
+ Because auto reloading is rarely useful this is disabled per default.
+ """
+
+ def __init__(self, mapping):
+ self.mapping = mapping
+
+ def get_source(self, environment, template):
+ if template in self.mapping:
+ source = self.mapping[template]
+ return source, None, lambda: source == self.mapping.get(template)
+ raise TemplateNotFound(template)
+
+ def list_templates(self):
+ return sorted(self.mapping)
+
+
+class FunctionLoader(BaseLoader):
+ """A loader that is passed a function which does the loading. The
+ function receives the name of the template and has to return either
+ an unicode string with the template source, a tuple in the form ``(source,
+ filename, uptodatefunc)`` or `None` if the template does not exist.
+
+ >>> def load_template(name):
+ ... if name == 'index.html':
+ ... return '...'
+ ...
+ >>> loader = FunctionLoader(load_template)
+
+ The `uptodatefunc` is a function that is called if autoreload is enabled
+ and has to return `True` if the template is still up to date. For more
+ details have a look at :meth:`BaseLoader.get_source` which has the same
+ return value.
+ """
+
+ def __init__(self, load_func):
+ self.load_func = load_func
+
+ def get_source(self, environment, template):
+ rv = self.load_func(template)
+ if rv is None:
+ raise TemplateNotFound(template)
+ elif isinstance(rv, string_types):
+ return rv, None, None
+ return rv
+
+
+class PrefixLoader(BaseLoader):
+ """A loader that is passed a dict of loaders where each loader is bound
+ to a prefix. The prefix is delimited from the template by a slash per
+ default, which can be changed by setting the `delimiter` argument to
+ something else::
+
+ loader = PrefixLoader({
+ 'app1': PackageLoader('mypackage.app1'),
+ 'app2': PackageLoader('mypackage.app2')
+ })
+
+ By loading ``'app1/index.html'`` the file from the app1 package is loaded,
+ by loading ``'app2/index.html'`` the file from the second.
+ """
+
+ def __init__(self, mapping, delimiter='/'):
+ self.mapping = mapping
+ self.delimiter = delimiter
+
+ def get_loader(self, template):
+ try:
+ prefix, name = template.split(self.delimiter, 1)
+ loader = self.mapping[prefix]
+ except (ValueError, KeyError):
+ raise TemplateNotFound(template)
+ return loader, name
+
+ def get_source(self, environment, template):
+ loader, name = self.get_loader(template)
+ try:
+ return loader.get_source(environment, name)
+ except TemplateNotFound:
+ # re-raise the exception with the correct fileame here.
+ # (the one that includes the prefix)
+ raise TemplateNotFound(template)
+
+ @internalcode
+ def load(self, environment, name, globals=None):
+ loader, local_name = self.get_loader(name)
+ try:
+ return loader.load(environment, local_name, globals)
+ except TemplateNotFound:
+ # re-raise the exception with the correct fileame here.
+ # (the one that includes the prefix)
+ raise TemplateNotFound(name)
+
+ def list_templates(self):
+ result = []
+ for prefix, loader in iteritems(self.mapping):
+ for template in loader.list_templates():
+ result.append(prefix + self.delimiter + template)
+ return result
+
+
+class ChoiceLoader(BaseLoader):
+ """This loader works like the `PrefixLoader` just that no prefix is
+ specified. If a template could not be found by one loader the next one
+ is tried.
+
+ >>> loader = ChoiceLoader([
+ ... FileSystemLoader('/path/to/user/templates'),
+ ... FileSystemLoader('/path/to/system/templates')
+ ... ])
+
+ This is useful if you want to allow users to override builtin templates
+ from a different location.
+ """
+
+ def __init__(self, loaders):
+ self.loaders = loaders
+
+ def get_source(self, environment, template):
+ for loader in self.loaders:
+ try:
+ return loader.get_source(environment, template)
+ except TemplateNotFound:
+ pass
+ raise TemplateNotFound(template)
+
+ @internalcode
+ def load(self, environment, name, globals=None):
+ for loader in self.loaders:
+ try:
+ return loader.load(environment, name, globals)
+ except TemplateNotFound:
+ pass
+ raise TemplateNotFound(name)
+
+ def list_templates(self):
+ found = set()
+ for loader in self.loaders:
+ found.update(loader.list_templates())
+ return sorted(found)
+
+
+class _TemplateModule(ModuleType):
+ """Like a normal module but with support for weak references"""
+
+
+class ModuleLoader(BaseLoader):
+ """This loader loads templates from precompiled templates.
+
+ Example usage:
+
+ >>> loader = ChoiceLoader([
+ ... ModuleLoader('/path/to/compiled/templates'),
+ ... FileSystemLoader('/path/to/templates')
+ ... ])
+
+ Templates can be precompiled with :meth:`Environment.compile_templates`.
+ """
+
+ has_source_access = False
+
+ def __init__(self, path):
+ package_name = '_jinja2_module_templates_%x' % id(self)
+
+ # create a fake module that looks for the templates in the
+ # path given.
+ mod = _TemplateModule(package_name)
+ if isinstance(path, string_types):
+ path = [path]
+ else:
+ path = list(path)
+ mod.__path__ = path
+
+ sys.modules[package_name] = weakref.proxy(mod,
+ lambda x: sys.modules.pop(package_name, None))
+
+ # the only strong reference, the sys.modules entry is weak
+ # so that the garbage collector can remove it once the
+ # loader that created it goes out of business.
+ self.module = mod
+ self.package_name = package_name
+
+ @staticmethod
+ def get_template_key(name):
+ return 'tmpl_' + sha1(name.encode('utf-8')).hexdigest()
+
+ @staticmethod
+ def get_module_filename(name):
+ return ModuleLoader.get_template_key(name) + '.py'
+
+ @internalcode
+ def load(self, environment, name, globals=None):
+ key = self.get_template_key(name)
+ module = '%s.%s' % (self.package_name, key)
+ mod = getattr(self.module, module, None)
+ if mod is None:
+ try:
+ mod = __import__(module, None, None, ['root'])
+ except ImportError:
+ raise TemplateNotFound(name)
+
+ # remove the entry from sys.modules, we only want the attribute
+ # on the module object we have stored on the loader.
+ sys.modules.pop(module, None)
+
+ return environment.template_class.from_module_dict(
+ environment, mod.__dict__, globals)
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/meta.py b/deps/v8_inspector/deps/jinja2/jinja2/meta.py
new file mode 100644
index 0000000000..3dbab7c22d
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/meta.py
@@ -0,0 +1,103 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.meta
+ ~~~~~~~~~~~
+
+ This module implements various functions that exposes information about
+ templates that might be interesting for various kinds of applications.
+
+ :copyright: (c) 2010 by the Jinja Team, see AUTHORS for more details.
+ :license: BSD, see LICENSE for more details.
+"""
+from jinja2 import nodes
+from jinja2.compiler import CodeGenerator
+from jinja2._compat import string_types
+
+
+class TrackingCodeGenerator(CodeGenerator):
+ """We abuse the code generator for introspection."""
+
+ def __init__(self, environment):
+ CodeGenerator.__init__(self, environment, '<introspection>',
+ '<introspection>')
+ self.undeclared_identifiers = set()
+
+ def write(self, x):
+ """Don't write."""
+
+ def pull_locals(self, frame):
+ """Remember all undeclared identifiers."""
+ self.undeclared_identifiers.update(frame.identifiers.undeclared)
+
+
+def find_undeclared_variables(ast):
+ """Returns a set of all variables in the AST that will be looked up from
+ the context at runtime. Because at compile time it's not known which
+ variables will be used depending on the path the execution takes at
+ runtime, all variables are returned.
+
+ >>> from jinja2 import Environment, meta
+ >>> env = Environment()
+ >>> ast = env.parse('{% set foo = 42 %}{{ bar + foo }}')
+ >>> meta.find_undeclared_variables(ast) == set(['bar'])
+ True
+
+ .. admonition:: Implementation
+
+ Internally the code generator is used for finding undeclared variables.
+ This is good to know because the code generator might raise a
+ :exc:`TemplateAssertionError` during compilation and as a matter of
+ fact this function can currently raise that exception as well.
+ """
+ codegen = TrackingCodeGenerator(ast.environment)
+ codegen.visit(ast)
+ return codegen.undeclared_identifiers
+
+
+def find_referenced_templates(ast):
+ """Finds all the referenced templates from the AST. This will return an
+ iterator over all the hardcoded template extensions, inclusions and
+ imports. If dynamic inheritance or inclusion is used, `None` will be
+ yielded.
+
+ >>> from jinja2 import Environment, meta
+ >>> env = Environment()
+ >>> ast = env.parse('{% extends "layout.html" %}{% include helper %}')
+ >>> list(meta.find_referenced_templates(ast))
+ ['layout.html', None]
+
+ This function is useful for dependency tracking. For example if you want
+ to rebuild parts of the website after a layout template has changed.
+ """
+ for node in ast.find_all((nodes.Extends, nodes.FromImport, nodes.Import,
+ nodes.Include)):
+ if not isinstance(node.template, nodes.Const):
+ # a tuple with some non consts in there
+ if isinstance(node.template, (nodes.Tuple, nodes.List)):
+ for template_name in node.template.items:
+ # something const, only yield the strings and ignore
+ # non-string consts that really just make no sense
+ if isinstance(template_name, nodes.Const):
+ if isinstance(template_name.value, string_types):
+ yield template_name.value
+ # something dynamic in there
+ else:
+ yield None
+ # something dynamic we don't know about here
+ else:
+ yield None
+ continue
+ # constant is a basestring, direct template name
+ if isinstance(node.template.value, string_types):
+ yield node.template.value
+ # a tuple or list (latter *should* not happen) made of consts,
+ # yield the consts that are strings. We could warn here for
+ # non string values
+ elif isinstance(node, nodes.Include) and \
+ isinstance(node.template.value, (tuple, list)):
+ for template_name in node.template.value:
+ if isinstance(template_name, string_types):
+ yield template_name
+ # something else we don't care about, we could warn here
+ else:
+ yield None
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/nodes.py b/deps/v8_inspector/deps/jinja2/jinja2/nodes.py
new file mode 100644
index 0000000000..d32046ce5c
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/nodes.py
@@ -0,0 +1,919 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.nodes
+ ~~~~~~~~~~~~
+
+ This module implements additional nodes derived from the ast base node.
+
+ It also provides some node tree helper functions like `in_lineno` and
+ `get_nodes` used by the parser and translator in order to normalize
+ python and jinja nodes.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import types
+import operator
+
+from collections import deque
+from jinja2.utils import Markup
+from jinja2._compat import izip, with_metaclass, text_type
+
+
+#: the types we support for context functions
+_context_function_types = (types.FunctionType, types.MethodType)
+
+
+_binop_to_func = {
+ '*': operator.mul,
+ '/': operator.truediv,
+ '//': operator.floordiv,
+ '**': operator.pow,
+ '%': operator.mod,
+ '+': operator.add,
+ '-': operator.sub
+}
+
+_uaop_to_func = {
+ 'not': operator.not_,
+ '+': operator.pos,
+ '-': operator.neg
+}
+
+_cmpop_to_func = {
+ 'eq': operator.eq,
+ 'ne': operator.ne,
+ 'gt': operator.gt,
+ 'gteq': operator.ge,
+ 'lt': operator.lt,
+ 'lteq': operator.le,
+ 'in': lambda a, b: a in b,
+ 'notin': lambda a, b: a not in b
+}
+
+
+class Impossible(Exception):
+ """Raised if the node could not perform a requested action."""
+
+
+class NodeType(type):
+ """A metaclass for nodes that handles the field and attribute
+ inheritance. fields and attributes from the parent class are
+ automatically forwarded to the child."""
+
+ def __new__(cls, name, bases, d):
+ for attr in 'fields', 'attributes':
+ storage = []
+ storage.extend(getattr(bases[0], attr, ()))
+ storage.extend(d.get(attr, ()))
+ assert len(bases) == 1, 'multiple inheritance not allowed'
+ assert len(storage) == len(set(storage)), 'layout conflict'
+ d[attr] = tuple(storage)
+ d.setdefault('abstract', False)
+ return type.__new__(cls, name, bases, d)
+
+
+class EvalContext(object):
+ """Holds evaluation time information. Custom attributes can be attached
+ to it in extensions.
+ """
+
+ def __init__(self, environment, template_name=None):
+ self.environment = environment
+ if callable(environment.autoescape):
+ self.autoescape = environment.autoescape(template_name)
+ else:
+ self.autoescape = environment.autoescape
+ self.volatile = False
+
+ def save(self):
+ return self.__dict__.copy()
+
+ def revert(self, old):
+ self.__dict__.clear()
+ self.__dict__.update(old)
+
+
+def get_eval_context(node, ctx):
+ if ctx is None:
+ if node.environment is None:
+ raise RuntimeError('if no eval context is passed, the '
+ 'node must have an attached '
+ 'environment.')
+ return EvalContext(node.environment)
+ return ctx
+
+
+class Node(with_metaclass(NodeType, object)):
+ """Baseclass for all Jinja2 nodes. There are a number of nodes available
+ of different types. There are four major types:
+
+ - :class:`Stmt`: statements
+ - :class:`Expr`: expressions
+ - :class:`Helper`: helper nodes
+ - :class:`Template`: the outermost wrapper node
+
+ All nodes have fields and attributes. Fields may be other nodes, lists,
+ or arbitrary values. Fields are passed to the constructor as regular
+ positional arguments, attributes as keyword arguments. Each node has
+ two attributes: `lineno` (the line number of the node) and `environment`.
+ The `environment` attribute is set at the end of the parsing process for
+ all nodes automatically.
+ """
+ fields = ()
+ attributes = ('lineno', 'environment')
+ abstract = True
+
+ def __init__(self, *fields, **attributes):
+ if self.abstract:
+ raise TypeError('abstract nodes are not instanciable')
+ if fields:
+ if len(fields) != len(self.fields):
+ if not self.fields:
+ raise TypeError('%r takes 0 arguments' %
+ self.__class__.__name__)
+ raise TypeError('%r takes 0 or %d argument%s' % (
+ self.__class__.__name__,
+ len(self.fields),
+ len(self.fields) != 1 and 's' or ''
+ ))
+ for name, arg in izip(self.fields, fields):
+ setattr(self, name, arg)
+ for attr in self.attributes:
+ setattr(self, attr, attributes.pop(attr, None))
+ if attributes:
+ raise TypeError('unknown attribute %r' %
+ next(iter(attributes)))
+
+ def iter_fields(self, exclude=None, only=None):
+ """This method iterates over all fields that are defined and yields
+ ``(key, value)`` tuples. Per default all fields are returned, but
+ it's possible to limit that to some fields by providing the `only`
+ parameter or to exclude some using the `exclude` parameter. Both
+ should be sets or tuples of field names.
+ """
+ for name in self.fields:
+ if (exclude is only is None) or \
+ (exclude is not None and name not in exclude) or \
+ (only is not None and name in only):
+ try:
+ yield name, getattr(self, name)
+ except AttributeError:
+ pass
+
+ def iter_child_nodes(self, exclude=None, only=None):
+ """Iterates over all direct child nodes of the node. This iterates
+ over all fields and yields the values of they are nodes. If the value
+ of a field is a list all the nodes in that list are returned.
+ """
+ for field, item in self.iter_fields(exclude, only):
+ if isinstance(item, list):
+ for n in item:
+ if isinstance(n, Node):
+ yield n
+ elif isinstance(item, Node):
+ yield item
+
+ def find(self, node_type):
+ """Find the first node of a given type. If no such node exists the
+ return value is `None`.
+ """
+ for result in self.find_all(node_type):
+ return result
+
+ def find_all(self, node_type):
+ """Find all the nodes of a given type. If the type is a tuple,
+ the check is performed for any of the tuple items.
+ """
+ for child in self.iter_child_nodes():
+ if isinstance(child, node_type):
+ yield child
+ for result in child.find_all(node_type):
+ yield result
+
+ def set_ctx(self, ctx):
+ """Reset the context of a node and all child nodes. Per default the
+ parser will all generate nodes that have a 'load' context as it's the
+ most common one. This method is used in the parser to set assignment
+ targets and other nodes to a store context.
+ """
+ todo = deque([self])
+ while todo:
+ node = todo.popleft()
+ if 'ctx' in node.fields:
+ node.ctx = ctx
+ todo.extend(node.iter_child_nodes())
+ return self
+
+ def set_lineno(self, lineno, override=False):
+ """Set the line numbers of the node and children."""
+ todo = deque([self])
+ while todo:
+ node = todo.popleft()
+ if 'lineno' in node.attributes:
+ if node.lineno is None or override:
+ node.lineno = lineno
+ todo.extend(node.iter_child_nodes())
+ return self
+
+ def set_environment(self, environment):
+ """Set the environment for all nodes."""
+ todo = deque([self])
+ while todo:
+ node = todo.popleft()
+ node.environment = environment
+ todo.extend(node.iter_child_nodes())
+ return self
+
+ def __eq__(self, other):
+ return type(self) is type(other) and \
+ tuple(self.iter_fields()) == tuple(other.iter_fields())
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ # Restore Python 2 hashing behavior on Python 3
+ __hash__ = object.__hash__
+
+ def __repr__(self):
+ return '%s(%s)' % (
+ self.__class__.__name__,
+ ', '.join('%s=%r' % (arg, getattr(self, arg, None)) for
+ arg in self.fields)
+ )
+
+
+class Stmt(Node):
+ """Base node for all statements."""
+ abstract = True
+
+
+class Helper(Node):
+ """Nodes that exist in a specific context only."""
+ abstract = True
+
+
+class Template(Node):
+ """Node that represents a template. This must be the outermost node that
+ is passed to the compiler.
+ """
+ fields = ('body',)
+
+
+class Output(Stmt):
+ """A node that holds multiple expressions which are then printed out.
+ This is used both for the `print` statement and the regular template data.
+ """
+ fields = ('nodes',)
+
+
+class Extends(Stmt):
+ """Represents an extends statement."""
+ fields = ('template',)
+
+
+class For(Stmt):
+ """The for loop. `target` is the target for the iteration (usually a
+ :class:`Name` or :class:`Tuple`), `iter` the iterable. `body` is a list
+ of nodes that are used as loop-body, and `else_` a list of nodes for the
+ `else` block. If no else node exists it has to be an empty list.
+
+ For filtered nodes an expression can be stored as `test`, otherwise `None`.
+ """
+ fields = ('target', 'iter', 'body', 'else_', 'test', 'recursive')
+
+
+class If(Stmt):
+ """If `test` is true, `body` is rendered, else `else_`."""
+ fields = ('test', 'body', 'else_')
+
+
+class Macro(Stmt):
+ """A macro definition. `name` is the name of the macro, `args` a list of
+ arguments and `defaults` a list of defaults if there are any. `body` is
+ a list of nodes for the macro body.
+ """
+ fields = ('name', 'args', 'defaults', 'body')
+
+
+class CallBlock(Stmt):
+ """Like a macro without a name but a call instead. `call` is called with
+ the unnamed macro as `caller` argument this node holds.
+ """
+ fields = ('call', 'args', 'defaults', 'body')
+
+
+class FilterBlock(Stmt):
+ """Node for filter sections."""
+ fields = ('body', 'filter')
+
+
+class Block(Stmt):
+ """A node that represents a block."""
+ fields = ('name', 'body', 'scoped')
+
+
+class Include(Stmt):
+ """A node that represents the include tag."""
+ fields = ('template', 'with_context', 'ignore_missing')
+
+
+class Import(Stmt):
+ """A node that represents the import tag."""
+ fields = ('template', 'target', 'with_context')
+
+
+class FromImport(Stmt):
+ """A node that represents the from import tag. It's important to not
+ pass unsafe names to the name attribute. The compiler translates the
+ attribute lookups directly into getattr calls and does *not* use the
+ subscript callback of the interface. As exported variables may not
+ start with double underscores (which the parser asserts) this is not a
+ problem for regular Jinja code, but if this node is used in an extension
+ extra care must be taken.
+
+ The list of names may contain tuples if aliases are wanted.
+ """
+ fields = ('template', 'names', 'with_context')
+
+
+class ExprStmt(Stmt):
+ """A statement that evaluates an expression and discards the result."""
+ fields = ('node',)
+
+
+class Assign(Stmt):
+ """Assigns an expression to a target."""
+ fields = ('target', 'node')
+
+
+class AssignBlock(Stmt):
+ """Assigns a block to a target."""
+ fields = ('target', 'body')
+
+
+class Expr(Node):
+ """Baseclass for all expressions."""
+ abstract = True
+
+ def as_const(self, eval_ctx=None):
+ """Return the value of the expression as constant or raise
+ :exc:`Impossible` if this was not possible.
+
+ An :class:`EvalContext` can be provided, if none is given
+ a default context is created which requires the nodes to have
+ an attached environment.
+
+ .. versionchanged:: 2.4
+ the `eval_ctx` parameter was added.
+ """
+ raise Impossible()
+
+ def can_assign(self):
+ """Check if it's possible to assign something to this node."""
+ return False
+
+
+class BinExpr(Expr):
+ """Baseclass for all binary expressions."""
+ fields = ('left', 'right')
+ operator = None
+ abstract = True
+
+ def as_const(self, eval_ctx=None):
+ eval_ctx = get_eval_context(self, eval_ctx)
+ # intercepted operators cannot be folded at compile time
+ if self.environment.sandboxed and \
+ self.operator in self.environment.intercepted_binops:
+ raise Impossible()
+ f = _binop_to_func[self.operator]
+ try:
+ return f(self.left.as_const(eval_ctx), self.right.as_const(eval_ctx))
+ except Exception:
+ raise Impossible()
+
+
+class UnaryExpr(Expr):
+ """Baseclass for all unary expressions."""
+ fields = ('node',)
+ operator = None
+ abstract = True
+
+ def as_const(self, eval_ctx=None):
+ eval_ctx = get_eval_context(self, eval_ctx)
+ # intercepted operators cannot be folded at compile time
+ if self.environment.sandboxed and \
+ self.operator in self.environment.intercepted_unops:
+ raise Impossible()
+ f = _uaop_to_func[self.operator]
+ try:
+ return f(self.node.as_const(eval_ctx))
+ except Exception:
+ raise Impossible()
+
+
+class Name(Expr):
+ """Looks up a name or stores a value in a name.
+ The `ctx` of the node can be one of the following values:
+
+ - `store`: store a value in the name
+ - `load`: load that name
+ - `param`: like `store` but if the name was defined as function parameter.
+ """
+ fields = ('name', 'ctx')
+
+ def can_assign(self):
+ return self.name not in ('true', 'false', 'none',
+ 'True', 'False', 'None')
+
+
+class Literal(Expr):
+ """Baseclass for literals."""
+ abstract = True
+
+
+class Const(Literal):
+ """All constant values. The parser will return this node for simple
+ constants such as ``42`` or ``"foo"`` but it can be used to store more
+ complex values such as lists too. Only constants with a safe
+ representation (objects where ``eval(repr(x)) == x`` is true).
+ """
+ fields = ('value',)
+
+ def as_const(self, eval_ctx=None):
+ return self.value
+
+ @classmethod
+ def from_untrusted(cls, value, lineno=None, environment=None):
+ """Return a const object if the value is representable as
+ constant value in the generated code, otherwise it will raise
+ an `Impossible` exception.
+ """
+ from .compiler import has_safe_repr
+ if not has_safe_repr(value):
+ raise Impossible()
+ return cls(value, lineno=lineno, environment=environment)
+
+
+class TemplateData(Literal):
+ """A constant template string."""
+ fields = ('data',)
+
+ def as_const(self, eval_ctx=None):
+ eval_ctx = get_eval_context(self, eval_ctx)
+ if eval_ctx.volatile:
+ raise Impossible()
+ if eval_ctx.autoescape:
+ return Markup(self.data)
+ return self.data
+
+
+class Tuple(Literal):
+ """For loop unpacking and some other things like multiple arguments
+ for subscripts. Like for :class:`Name` `ctx` specifies if the tuple
+ is used for loading the names or storing.
+ """
+ fields = ('items', 'ctx')
+
+ def as_const(self, eval_ctx=None):
+ eval_ctx = get_eval_context(self, eval_ctx)
+ return tuple(x.as_const(eval_ctx) for x in self.items)
+
+ def can_assign(self):
+ for item in self.items:
+ if not item.can_assign():
+ return False
+ return True
+
+
+class List(Literal):
+ """Any list literal such as ``[1, 2, 3]``"""
+ fields = ('items',)
+
+ def as_const(self, eval_ctx=None):
+ eval_ctx = get_eval_context(self, eval_ctx)
+ return [x.as_const(eval_ctx) for x in self.items]
+
+
+class Dict(Literal):
+ """Any dict literal such as ``{1: 2, 3: 4}``. The items must be a list of
+ :class:`Pair` nodes.
+ """
+ fields = ('items',)
+
+ def as_const(self, eval_ctx=None):
+ eval_ctx = get_eval_context(self, eval_ctx)
+ return dict(x.as_const(eval_ctx) for x in self.items)
+
+
+class Pair(Helper):
+ """A key, value pair for dicts."""
+ fields = ('key', 'value')
+
+ def as_const(self, eval_ctx=None):
+ eval_ctx = get_eval_context(self, eval_ctx)
+ return self.key.as_const(eval_ctx), self.value.as_const(eval_ctx)
+
+
+class Keyword(Helper):
+ """A key, value pair for keyword arguments where key is a string."""
+ fields = ('key', 'value')
+
+ def as_const(self, eval_ctx=None):
+ eval_ctx = get_eval_context(self, eval_ctx)
+ return self.key, self.value.as_const(eval_ctx)
+
+
+class CondExpr(Expr):
+ """A conditional expression (inline if expression). (``{{
+ foo if bar else baz }}``)
+ """
+ fields = ('test', 'expr1', 'expr2')
+
+ def as_const(self, eval_ctx=None):
+ eval_ctx = get_eval_context(self, eval_ctx)
+ if self.test.as_const(eval_ctx):
+ return self.expr1.as_const(eval_ctx)
+
+ # if we evaluate to an undefined object, we better do that at runtime
+ if self.expr2 is None:
+ raise Impossible()
+
+ return self.expr2.as_const(eval_ctx)
+
+
+class Filter(Expr):
+ """This node applies a filter on an expression. `name` is the name of
+ the filter, the rest of the fields are the same as for :class:`Call`.
+
+ If the `node` of a filter is `None` the contents of the last buffer are
+ filtered. Buffers are created by macros and filter blocks.
+ """
+ fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
+
+ def as_const(self, eval_ctx=None):
+ eval_ctx = get_eval_context(self, eval_ctx)
+ if eval_ctx.volatile or self.node is None:
+ raise Impossible()
+ # we have to be careful here because we call filter_ below.
+ # if this variable would be called filter, 2to3 would wrap the
+ # call in a list beause it is assuming we are talking about the
+ # builtin filter function here which no longer returns a list in
+ # python 3. because of that, do not rename filter_ to filter!
+ filter_ = self.environment.filters.get(self.name)
+ if filter_ is None or getattr(filter_, 'contextfilter', False):
+ raise Impossible()
+ obj = self.node.as_const(eval_ctx)
+ args = [x.as_const(eval_ctx) for x in self.args]
+ if getattr(filter_, 'evalcontextfilter', False):
+ args.insert(0, eval_ctx)
+ elif getattr(filter_, 'environmentfilter', False):
+ args.insert(0, self.environment)
+ kwargs = dict(x.as_const(eval_ctx) for x in self.kwargs)
+ if self.dyn_args is not None:
+ try:
+ args.extend(self.dyn_args.as_const(eval_ctx))
+ except Exception:
+ raise Impossible()
+ if self.dyn_kwargs is not None:
+ try:
+ kwargs.update(self.dyn_kwargs.as_const(eval_ctx))
+ except Exception:
+ raise Impossible()
+ try:
+ return filter_(obj, *args, **kwargs)
+ except Exception:
+ raise Impossible()
+
+
+class Test(Expr):
+ """Applies a test on an expression. `name` is the name of the test, the
+ rest of the fields are the same as for :class:`Call`.
+ """
+ fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
+
+
+class Call(Expr):
+ """Calls an expression. `args` is a list of arguments, `kwargs` a list
+ of keyword arguments (list of :class:`Keyword` nodes), and `dyn_args`
+ and `dyn_kwargs` has to be either `None` or a node that is used as
+ node for dynamic positional (``*args``) or keyword (``**kwargs``)
+ arguments.
+ """
+ fields = ('node', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
+
+ def as_const(self, eval_ctx=None):
+ eval_ctx = get_eval_context(self, eval_ctx)
+ if eval_ctx.volatile:
+ raise Impossible()
+ obj = self.node.as_const(eval_ctx)
+
+ # don't evaluate context functions
+ args = [x.as_const(eval_ctx) for x in self.args]
+ if isinstance(obj, _context_function_types):
+ if getattr(obj, 'contextfunction', False):
+ raise Impossible()
+ elif getattr(obj, 'evalcontextfunction', False):
+ args.insert(0, eval_ctx)
+ elif getattr(obj, 'environmentfunction', False):
+ args.insert(0, self.environment)
+
+ kwargs = dict(x.as_const(eval_ctx) for x in self.kwargs)
+ if self.dyn_args is not None:
+ try:
+ args.extend(self.dyn_args.as_const(eval_ctx))
+ except Exception:
+ raise Impossible()
+ if self.dyn_kwargs is not None:
+ try:
+ kwargs.update(self.dyn_kwargs.as_const(eval_ctx))
+ except Exception:
+ raise Impossible()
+ try:
+ return obj(*args, **kwargs)
+ except Exception:
+ raise Impossible()
+
+
+class Getitem(Expr):
+ """Get an attribute or item from an expression and prefer the item."""
+ fields = ('node', 'arg', 'ctx')
+
+ def as_const(self, eval_ctx=None):
+ eval_ctx = get_eval_context(self, eval_ctx)
+ if self.ctx != 'load':
+ raise Impossible()
+ try:
+ return self.environment.getitem(self.node.as_const(eval_ctx),
+ self.arg.as_const(eval_ctx))
+ except Exception:
+ raise Impossible()
+
+ def can_assign(self):
+ return False
+
+
+class Getattr(Expr):
+ """Get an attribute or item from an expression that is a ascii-only
+ bytestring and prefer the attribute.
+ """
+ fields = ('node', 'attr', 'ctx')
+
+ def as_const(self, eval_ctx=None):
+ if self.ctx != 'load':
+ raise Impossible()
+ try:
+ eval_ctx = get_eval_context(self, eval_ctx)
+ return self.environment.getattr(self.node.as_const(eval_ctx),
+ self.attr)
+ except Exception:
+ raise Impossible()
+
+ def can_assign(self):
+ return False
+
+
+class Slice(Expr):
+ """Represents a slice object. This must only be used as argument for
+ :class:`Subscript`.
+ """
+ fields = ('start', 'stop', 'step')
+
+ def as_const(self, eval_ctx=None):
+ eval_ctx = get_eval_context(self, eval_ctx)
+ def const(obj):
+ if obj is None:
+ return None
+ return obj.as_const(eval_ctx)
+ return slice(const(self.start), const(self.stop), const(self.step))
+
+
+class Concat(Expr):
+ """Concatenates the list of expressions provided after converting them to
+ unicode.
+ """
+ fields = ('nodes',)
+
+ def as_const(self, eval_ctx=None):
+ eval_ctx = get_eval_context(self, eval_ctx)
+ return ''.join(text_type(x.as_const(eval_ctx)) for x in self.nodes)
+
+
+class Compare(Expr):
+ """Compares an expression with some other expressions. `ops` must be a
+ list of :class:`Operand`\s.
+ """
+ fields = ('expr', 'ops')
+
+ def as_const(self, eval_ctx=None):
+ eval_ctx = get_eval_context(self, eval_ctx)
+ result = value = self.expr.as_const(eval_ctx)
+ try:
+ for op in self.ops:
+ new_value = op.expr.as_const(eval_ctx)
+ result = _cmpop_to_func[op.op](value, new_value)
+ value = new_value
+ except Exception:
+ raise Impossible()
+ return result
+
+
+class Operand(Helper):
+ """Holds an operator and an expression."""
+ fields = ('op', 'expr')
+
+if __debug__:
+ Operand.__doc__ += '\nThe following operators are available: ' + \
+ ', '.join(sorted('``%s``' % x for x in set(_binop_to_func) |
+ set(_uaop_to_func) | set(_cmpop_to_func)))
+
+
+class Mul(BinExpr):
+ """Multiplies the left with the right node."""
+ operator = '*'
+
+
+class Div(BinExpr):
+ """Divides the left by the right node."""
+ operator = '/'
+
+
+class FloorDiv(BinExpr):
+ """Divides the left by the right node and truncates conver the
+ result into an integer by truncating.
+ """
+ operator = '//'
+
+
+class Add(BinExpr):
+ """Add the left to the right node."""
+ operator = '+'
+
+
+class Sub(BinExpr):
+ """Subtract the right from the left node."""
+ operator = '-'
+
+
+class Mod(BinExpr):
+ """Left modulo right."""
+ operator = '%'
+
+
+class Pow(BinExpr):
+ """Left to the power of right."""
+ operator = '**'
+
+
+class And(BinExpr):
+ """Short circuited AND."""
+ operator = 'and'
+
+ def as_const(self, eval_ctx=None):
+ eval_ctx = get_eval_context(self, eval_ctx)
+ return self.left.as_const(eval_ctx) and self.right.as_const(eval_ctx)
+
+
+class Or(BinExpr):
+ """Short circuited OR."""
+ operator = 'or'
+
+ def as_const(self, eval_ctx=None):
+ eval_ctx = get_eval_context(self, eval_ctx)
+ return self.left.as_const(eval_ctx) or self.right.as_const(eval_ctx)
+
+
+class Not(UnaryExpr):
+ """Negate the expression."""
+ operator = 'not'
+
+
+class Neg(UnaryExpr):
+ """Make the expression negative."""
+ operator = '-'
+
+
+class Pos(UnaryExpr):
+ """Make the expression positive (noop for most expressions)"""
+ operator = '+'
+
+
+# Helpers for extensions
+
+
+class EnvironmentAttribute(Expr):
+ """Loads an attribute from the environment object. This is useful for
+ extensions that want to call a callback stored on the environment.
+ """
+ fields = ('name',)
+
+
+class ExtensionAttribute(Expr):
+ """Returns the attribute of an extension bound to the environment.
+ The identifier is the identifier of the :class:`Extension`.
+
+ This node is usually constructed by calling the
+ :meth:`~jinja2.ext.Extension.attr` method on an extension.
+ """
+ fields = ('identifier', 'name')
+
+
+class ImportedName(Expr):
+ """If created with an import name the import name is returned on node
+ access. For example ``ImportedName('cgi.escape')`` returns the `escape`
+ function from the cgi module on evaluation. Imports are optimized by the
+ compiler so there is no need to assign them to local variables.
+ """
+ fields = ('importname',)
+
+
+class InternalName(Expr):
+ """An internal name in the compiler. You cannot create these nodes
+ yourself but the parser provides a
+ :meth:`~jinja2.parser.Parser.free_identifier` method that creates
+ a new identifier for you. This identifier is not available from the
+ template and is not threated specially by the compiler.
+ """
+ fields = ('name',)
+
+ def __init__(self):
+ raise TypeError('Can\'t create internal names. Use the '
+ '`free_identifier` method on a parser.')
+
+
+class MarkSafe(Expr):
+ """Mark the wrapped expression as safe (wrap it as `Markup`)."""
+ fields = ('expr',)
+
+ def as_const(self, eval_ctx=None):
+ eval_ctx = get_eval_context(self, eval_ctx)
+ return Markup(self.expr.as_const(eval_ctx))
+
+
+class MarkSafeIfAutoescape(Expr):
+ """Mark the wrapped expression as safe (wrap it as `Markup`) but
+ only if autoescaping is active.
+
+ .. versionadded:: 2.5
+ """
+ fields = ('expr',)
+
+ def as_const(self, eval_ctx=None):
+ eval_ctx = get_eval_context(self, eval_ctx)
+ if eval_ctx.volatile:
+ raise Impossible()
+ expr = self.expr.as_const(eval_ctx)
+ if eval_ctx.autoescape:
+ return Markup(expr)
+ return expr
+
+
+class ContextReference(Expr):
+ """Returns the current template context. It can be used like a
+ :class:`Name` node, with a ``'load'`` ctx and will return the
+ current :class:`~jinja2.runtime.Context` object.
+
+ Here an example that assigns the current template name to a
+ variable named `foo`::
+
+ Assign(Name('foo', ctx='store'),
+ Getattr(ContextReference(), 'name'))
+ """
+
+
+class Continue(Stmt):
+ """Continue a loop."""
+
+
+class Break(Stmt):
+ """Break a loop."""
+
+
+class Scope(Stmt):
+ """An artificial scope."""
+ fields = ('body',)
+
+
+class EvalContextModifier(Stmt):
+ """Modifies the eval context. For each option that should be modified,
+ a :class:`Keyword` has to be added to the :attr:`options` list.
+
+ Example to change the `autoescape` setting::
+
+ EvalContextModifier(options=[Keyword('autoescape', Const(True))])
+ """
+ fields = ('options',)
+
+
+class ScopedEvalContextModifier(EvalContextModifier):
+ """Modifies the eval context and reverts it later. Works exactly like
+ :class:`EvalContextModifier` but will only modify the
+ :class:`~jinja2.nodes.EvalContext` for nodes in the :attr:`body`.
+ """
+ fields = ('body',)
+
+
+# make sure nobody creates custom nodes
+def _failing_new(*args, **kwargs):
+ raise TypeError('can\'t create custom node types')
+NodeType.__new__ = staticmethod(_failing_new); del _failing_new
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/optimizer.py b/deps/v8_inspector/deps/jinja2/jinja2/optimizer.py
new file mode 100644
index 0000000000..00eab115e1
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/optimizer.py
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.optimizer
+ ~~~~~~~~~~~~~~~~
+
+ The jinja optimizer is currently trying to constant fold a few expressions
+ and modify the AST in place so that it should be easier to evaluate it.
+
+ Because the AST does not contain all the scoping information and the
+ compiler has to find that out, we cannot do all the optimizations we
+ want. For example loop unrolling doesn't work because unrolled loops would
+ have a different scoping.
+
+ The solution would be a second syntax tree that has the scoping rules stored.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD.
+"""
+from jinja2 import nodes
+from jinja2.visitor import NodeTransformer
+
+
+def optimize(node, environment):
+ """The context hint can be used to perform an static optimization
+ based on the context given."""
+ optimizer = Optimizer(environment)
+ return optimizer.visit(node)
+
+
+class Optimizer(NodeTransformer):
+
+ def __init__(self, environment):
+ self.environment = environment
+
+ def visit_If(self, node):
+ """Eliminate dead code."""
+ # do not optimize ifs that have a block inside so that it doesn't
+ # break super().
+ if node.find(nodes.Block) is not None:
+ return self.generic_visit(node)
+ try:
+ val = self.visit(node.test).as_const()
+ except nodes.Impossible:
+ return self.generic_visit(node)
+ if val:
+ body = node.body
+ else:
+ body = node.else_
+ result = []
+ for node in body:
+ result.extend(self.visit_list(node))
+ return result
+
+ def fold(self, node):
+ """Do constant folding."""
+ node = self.generic_visit(node)
+ try:
+ return nodes.Const.from_untrusted(node.as_const(),
+ lineno=node.lineno,
+ environment=self.environment)
+ except nodes.Impossible:
+ return node
+
+ visit_Add = visit_Sub = visit_Mul = visit_Div = visit_FloorDiv = \
+ visit_Pow = visit_Mod = visit_And = visit_Or = visit_Pos = visit_Neg = \
+ visit_Not = visit_Compare = visit_Getitem = visit_Getattr = visit_Call = \
+ visit_Filter = visit_Test = visit_CondExpr = fold
+ del fold
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/parser.py b/deps/v8_inspector/deps/jinja2/jinja2/parser.py
new file mode 100644
index 0000000000..d24da180ea
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/parser.py
@@ -0,0 +1,899 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.parser
+ ~~~~~~~~~~~~~
+
+ Implements the template parser.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+from jinja2 import nodes
+from jinja2.exceptions import TemplateSyntaxError, TemplateAssertionError
+from jinja2.lexer import describe_token, describe_token_expr
+from jinja2._compat import imap
+
+
+_statement_keywords = frozenset(['for', 'if', 'block', 'extends', 'print',
+ 'macro', 'include', 'from', 'import',
+ 'set'])
+_compare_operators = frozenset(['eq', 'ne', 'lt', 'lteq', 'gt', 'gteq'])
+
+
+class Parser(object):
+ """This is the central parsing class Jinja2 uses. It's passed to
+ extensions and can be used to parse expressions or statements.
+ """
+
+ def __init__(self, environment, source, name=None, filename=None,
+ state=None):
+ self.environment = environment
+ self.stream = environment._tokenize(source, name, filename, state)
+ self.name = name
+ self.filename = filename
+ self.closed = False
+ self.extensions = {}
+ for extension in environment.iter_extensions():
+ for tag in extension.tags:
+ self.extensions[tag] = extension.parse
+ self._last_identifier = 0
+ self._tag_stack = []
+ self._end_token_stack = []
+
+ def fail(self, msg, lineno=None, exc=TemplateSyntaxError):
+ """Convenience method that raises `exc` with the message, passed
+ line number or last line number as well as the current name and
+ filename.
+ """
+ if lineno is None:
+ lineno = self.stream.current.lineno
+ raise exc(msg, lineno, self.name, self.filename)
+
+ def _fail_ut_eof(self, name, end_token_stack, lineno):
+ expected = []
+ for exprs in end_token_stack:
+ expected.extend(imap(describe_token_expr, exprs))
+ if end_token_stack:
+ currently_looking = ' or '.join(
+ "'%s'" % describe_token_expr(expr)
+ for expr in end_token_stack[-1])
+ else:
+ currently_looking = None
+
+ if name is None:
+ message = ['Unexpected end of template.']
+ else:
+ message = ['Encountered unknown tag \'%s\'.' % name]
+
+ if currently_looking:
+ if name is not None and name in expected:
+ message.append('You probably made a nesting mistake. Jinja '
+ 'is expecting this tag, but currently looking '
+ 'for %s.' % currently_looking)
+ else:
+ message.append('Jinja was looking for the following tags: '
+ '%s.' % currently_looking)
+
+ if self._tag_stack:
+ message.append('The innermost block that needs to be '
+ 'closed is \'%s\'.' % self._tag_stack[-1])
+
+ self.fail(' '.join(message), lineno)
+
+ def fail_unknown_tag(self, name, lineno=None):
+ """Called if the parser encounters an unknown tag. Tries to fail
+ with a human readable error message that could help to identify
+ the problem.
+ """
+ return self._fail_ut_eof(name, self._end_token_stack, lineno)
+
+ def fail_eof(self, end_tokens=None, lineno=None):
+ """Like fail_unknown_tag but for end of template situations."""
+ stack = list(self._end_token_stack)
+ if end_tokens is not None:
+ stack.append(end_tokens)
+ return self._fail_ut_eof(None, stack, lineno)
+
+ def is_tuple_end(self, extra_end_rules=None):
+ """Are we at the end of a tuple?"""
+ if self.stream.current.type in ('variable_end', 'block_end', 'rparen'):
+ return True
+ elif extra_end_rules is not None:
+ return self.stream.current.test_any(extra_end_rules)
+ return False
+
+ def free_identifier(self, lineno=None):
+ """Return a new free identifier as :class:`~jinja2.nodes.InternalName`."""
+ self._last_identifier += 1
+ rv = object.__new__(nodes.InternalName)
+ nodes.Node.__init__(rv, 'fi%d' % self._last_identifier, lineno=lineno)
+ return rv
+
+ def parse_statement(self):
+ """Parse a single statement."""
+ token = self.stream.current
+ if token.type != 'name':
+ self.fail('tag name expected', token.lineno)
+ self._tag_stack.append(token.value)
+ pop_tag = True
+ try:
+ if token.value in _statement_keywords:
+ return getattr(self, 'parse_' + self.stream.current.value)()
+ if token.value == 'call':
+ return self.parse_call_block()
+ if token.value == 'filter':
+ return self.parse_filter_block()
+ ext = self.extensions.get(token.value)
+ if ext is not None:
+ return ext(self)
+
+ # did not work out, remove the token we pushed by accident
+ # from the stack so that the unknown tag fail function can
+ # produce a proper error message.
+ self._tag_stack.pop()
+ pop_tag = False
+ self.fail_unknown_tag(token.value, token.lineno)
+ finally:
+ if pop_tag:
+ self._tag_stack.pop()
+
+ def parse_statements(self, end_tokens, drop_needle=False):
+ """Parse multiple statements into a list until one of the end tokens
+ is reached. This is used to parse the body of statements as it also
+ parses template data if appropriate. The parser checks first if the
+ current token is a colon and skips it if there is one. Then it checks
+ for the block end and parses until if one of the `end_tokens` is
+ reached. Per default the active token in the stream at the end of
+ the call is the matched end token. If this is not wanted `drop_needle`
+ can be set to `True` and the end token is removed.
+ """
+ # the first token may be a colon for python compatibility
+ self.stream.skip_if('colon')
+
+ # in the future it would be possible to add whole code sections
+ # by adding some sort of end of statement token and parsing those here.
+ self.stream.expect('block_end')
+ result = self.subparse(end_tokens)
+
+ # we reached the end of the template too early, the subparser
+ # does not check for this, so we do that now
+ if self.stream.current.type == 'eof':
+ self.fail_eof(end_tokens)
+
+ if drop_needle:
+ next(self.stream)
+ return result
+
+ def parse_set(self):
+ """Parse an assign statement."""
+ lineno = next(self.stream).lineno
+ target = self.parse_assign_target()
+ if self.stream.skip_if('assign'):
+ expr = self.parse_tuple()
+ return nodes.Assign(target, expr, lineno=lineno)
+ body = self.parse_statements(('name:endset',),
+ drop_needle=True)
+ return nodes.AssignBlock(target, body, lineno=lineno)
+
+ def parse_for(self):
+ """Parse a for loop."""
+ lineno = self.stream.expect('name:for').lineno
+ target = self.parse_assign_target(extra_end_rules=('name:in',))
+ self.stream.expect('name:in')
+ iter = self.parse_tuple(with_condexpr=False,
+ extra_end_rules=('name:recursive',))
+ test = None
+ if self.stream.skip_if('name:if'):
+ test = self.parse_expression()
+ recursive = self.stream.skip_if('name:recursive')
+ body = self.parse_statements(('name:endfor', 'name:else'))
+ if next(self.stream).value == 'endfor':
+ else_ = []
+ else:
+ else_ = self.parse_statements(('name:endfor',), drop_needle=True)
+ return nodes.For(target, iter, body, else_, test,
+ recursive, lineno=lineno)
+
+ def parse_if(self):
+ """Parse an if construct."""
+ node = result = nodes.If(lineno=self.stream.expect('name:if').lineno)
+ while 1:
+ node.test = self.parse_tuple(with_condexpr=False)
+ node.body = self.parse_statements(('name:elif', 'name:else',
+ 'name:endif'))
+ token = next(self.stream)
+ if token.test('name:elif'):
+ new_node = nodes.If(lineno=self.stream.current.lineno)
+ node.else_ = [new_node]
+ node = new_node
+ continue
+ elif token.test('name:else'):
+ node.else_ = self.parse_statements(('name:endif',),
+ drop_needle=True)
+ else:
+ node.else_ = []
+ break
+ return result
+
+ def parse_block(self):
+ node = nodes.Block(lineno=next(self.stream).lineno)
+ node.name = self.stream.expect('name').value
+ node.scoped = self.stream.skip_if('name:scoped')
+
+ # common problem people encounter when switching from django
+ # to jinja. we do not support hyphens in block names, so let's
+ # raise a nicer error message in that case.
+ if self.stream.current.type == 'sub':
+ self.fail('Block names in Jinja have to be valid Python '
+ 'identifiers and may not contain hyphens, use an '
+ 'underscore instead.')
+
+ node.body = self.parse_statements(('name:endblock',), drop_needle=True)
+ self.stream.skip_if('name:' + node.name)
+ return node
+
+ def parse_extends(self):
+ node = nodes.Extends(lineno=next(self.stream).lineno)
+ node.template = self.parse_expression()
+ return node
+
+ def parse_import_context(self, node, default):
+ if self.stream.current.test_any('name:with', 'name:without') and \
+ self.stream.look().test('name:context'):
+ node.with_context = next(self.stream).value == 'with'
+ self.stream.skip()
+ else:
+ node.with_context = default
+ return node
+
+ def parse_include(self):
+ node = nodes.Include(lineno=next(self.stream).lineno)
+ node.template = self.parse_expression()
+ if self.stream.current.test('name:ignore') and \
+ self.stream.look().test('name:missing'):
+ node.ignore_missing = True
+ self.stream.skip(2)
+ else:
+ node.ignore_missing = False
+ return self.parse_import_context(node, True)
+
+ def parse_import(self):
+ node = nodes.Import(lineno=next(self.stream).lineno)
+ node.template = self.parse_expression()
+ self.stream.expect('name:as')
+ node.target = self.parse_assign_target(name_only=True).name
+ return self.parse_import_context(node, False)
+
+ def parse_from(self):
+ node = nodes.FromImport(lineno=next(self.stream).lineno)
+ node.template = self.parse_expression()
+ self.stream.expect('name:import')
+ node.names = []
+
+ def parse_context():
+ if self.stream.current.value in ('with', 'without') and \
+ self.stream.look().test('name:context'):
+ node.with_context = next(self.stream).value == 'with'
+ self.stream.skip()
+ return True
+ return False
+
+ while 1:
+ if node.names:
+ self.stream.expect('comma')
+ if self.stream.current.type == 'name':
+ if parse_context():
+ break
+ target = self.parse_assign_target(name_only=True)
+ if target.name.startswith('_'):
+ self.fail('names starting with an underline can not '
+ 'be imported', target.lineno,
+ exc=TemplateAssertionError)
+ if self.stream.skip_if('name:as'):
+ alias = self.parse_assign_target(name_only=True)
+ node.names.append((target.name, alias.name))
+ else:
+ node.names.append(target.name)
+ if parse_context() or self.stream.current.type != 'comma':
+ break
+ else:
+ break
+ if not hasattr(node, 'with_context'):
+ node.with_context = False
+ self.stream.skip_if('comma')
+ return node
+
+ def parse_signature(self, node):
+ node.args = args = []
+ node.defaults = defaults = []
+ self.stream.expect('lparen')
+ while self.stream.current.type != 'rparen':
+ if args:
+ self.stream.expect('comma')
+ arg = self.parse_assign_target(name_only=True)
+ arg.set_ctx('param')
+ if self.stream.skip_if('assign'):
+ defaults.append(self.parse_expression())
+ elif defaults:
+ self.fail('non-default argument follows default argument')
+ args.append(arg)
+ self.stream.expect('rparen')
+
+ def parse_call_block(self):
+ node = nodes.CallBlock(lineno=next(self.stream).lineno)
+ if self.stream.current.type == 'lparen':
+ self.parse_signature(node)
+ else:
+ node.args = []
+ node.defaults = []
+
+ node.call = self.parse_expression()
+ if not isinstance(node.call, nodes.Call):
+ self.fail('expected call', node.lineno)
+ node.body = self.parse_statements(('name:endcall',), drop_needle=True)
+ return node
+
+ def parse_filter_block(self):
+ node = nodes.FilterBlock(lineno=next(self.stream).lineno)
+ node.filter = self.parse_filter(None, start_inline=True)
+ node.body = self.parse_statements(('name:endfilter',),
+ drop_needle=True)
+ return node
+
+ def parse_macro(self):
+ node = nodes.Macro(lineno=next(self.stream).lineno)
+ node.name = self.parse_assign_target(name_only=True).name
+ self.parse_signature(node)
+ node.body = self.parse_statements(('name:endmacro',),
+ drop_needle=True)
+ return node
+
+ def parse_print(self):
+ node = nodes.Output(lineno=next(self.stream).lineno)
+ node.nodes = []
+ while self.stream.current.type != 'block_end':
+ if node.nodes:
+ self.stream.expect('comma')
+ node.nodes.append(self.parse_expression())
+ return node
+
+ def parse_assign_target(self, with_tuple=True, name_only=False,
+ extra_end_rules=None):
+ """Parse an assignment target. As Jinja2 allows assignments to
+ tuples, this function can parse all allowed assignment targets. Per
+ default assignments to tuples are parsed, that can be disable however
+ by setting `with_tuple` to `False`. If only assignments to names are
+ wanted `name_only` can be set to `True`. The `extra_end_rules`
+ parameter is forwarded to the tuple parsing function.
+ """
+ if name_only:
+ token = self.stream.expect('name')
+ target = nodes.Name(token.value, 'store', lineno=token.lineno)
+ else:
+ if with_tuple:
+ target = self.parse_tuple(simplified=True,
+ extra_end_rules=extra_end_rules)
+ else:
+ target = self.parse_primary()
+ target.set_ctx('store')
+ if not target.can_assign():
+ self.fail('can\'t assign to %r' % target.__class__.
+ __name__.lower(), target.lineno)
+ return target
+
+ def parse_expression(self, with_condexpr=True):
+ """Parse an expression. Per default all expressions are parsed, if
+ the optional `with_condexpr` parameter is set to `False` conditional
+ expressions are not parsed.
+ """
+ if with_condexpr:
+ return self.parse_condexpr()
+ return self.parse_or()
+
+ def parse_condexpr(self):
+ lineno = self.stream.current.lineno
+ expr1 = self.parse_or()
+ while self.stream.skip_if('name:if'):
+ expr2 = self.parse_or()
+ if self.stream.skip_if('name:else'):
+ expr3 = self.parse_condexpr()
+ else:
+ expr3 = None
+ expr1 = nodes.CondExpr(expr2, expr1, expr3, lineno=lineno)
+ lineno = self.stream.current.lineno
+ return expr1
+
+ def parse_or(self):
+ lineno = self.stream.current.lineno
+ left = self.parse_and()
+ while self.stream.skip_if('name:or'):
+ right = self.parse_and()
+ left = nodes.Or(left, right, lineno=lineno)
+ lineno = self.stream.current.lineno
+ return left
+
+ def parse_and(self):
+ lineno = self.stream.current.lineno
+ left = self.parse_not()
+ while self.stream.skip_if('name:and'):
+ right = self.parse_not()
+ left = nodes.And(left, right, lineno=lineno)
+ lineno = self.stream.current.lineno
+ return left
+
+ def parse_not(self):
+ if self.stream.current.test('name:not'):
+ lineno = next(self.stream).lineno
+ return nodes.Not(self.parse_not(), lineno=lineno)
+ return self.parse_compare()
+
+ def parse_compare(self):
+ lineno = self.stream.current.lineno
+ expr = self.parse_add()
+ ops = []
+ while 1:
+ token_type = self.stream.current.type
+ if token_type in _compare_operators:
+ next(self.stream)
+ ops.append(nodes.Operand(token_type, self.parse_add()))
+ elif self.stream.skip_if('name:in'):
+ ops.append(nodes.Operand('in', self.parse_add()))
+ elif (self.stream.current.test('name:not') and
+ self.stream.look().test('name:in')):
+ self.stream.skip(2)
+ ops.append(nodes.Operand('notin', self.parse_add()))
+ else:
+ break
+ lineno = self.stream.current.lineno
+ if not ops:
+ return expr
+ return nodes.Compare(expr, ops, lineno=lineno)
+
+ def parse_add(self):
+ lineno = self.stream.current.lineno
+ left = self.parse_sub()
+ while self.stream.current.type == 'add':
+ next(self.stream)
+ right = self.parse_sub()
+ left = nodes.Add(left, right, lineno=lineno)
+ lineno = self.stream.current.lineno
+ return left
+
+ def parse_sub(self):
+ lineno = self.stream.current.lineno
+ left = self.parse_concat()
+ while self.stream.current.type == 'sub':
+ next(self.stream)
+ right = self.parse_concat()
+ left = nodes.Sub(left, right, lineno=lineno)
+ lineno = self.stream.current.lineno
+ return left
+
+ def parse_concat(self):
+ lineno = self.stream.current.lineno
+ args = [self.parse_mul()]
+ while self.stream.current.type == 'tilde':
+ next(self.stream)
+ args.append(self.parse_mul())
+ if len(args) == 1:
+ return args[0]
+ return nodes.Concat(args, lineno=lineno)
+
+ def parse_mul(self):
+ lineno = self.stream.current.lineno
+ left = self.parse_div()
+ while self.stream.current.type == 'mul':
+ next(self.stream)
+ right = self.parse_div()
+ left = nodes.Mul(left, right, lineno=lineno)
+ lineno = self.stream.current.lineno
+ return left
+
+ def parse_div(self):
+ lineno = self.stream.current.lineno
+ left = self.parse_floordiv()
+ while self.stream.current.type == 'div':
+ next(self.stream)
+ right = self.parse_floordiv()
+ left = nodes.Div(left, right, lineno=lineno)
+ lineno = self.stream.current.lineno
+ return left
+
+ def parse_floordiv(self):
+ lineno = self.stream.current.lineno
+ left = self.parse_mod()
+ while self.stream.current.type == 'floordiv':
+ next(self.stream)
+ right = self.parse_mod()
+ left = nodes.FloorDiv(left, right, lineno=lineno)
+ lineno = self.stream.current.lineno
+ return left
+
+ def parse_mod(self):
+ lineno = self.stream.current.lineno
+ left = self.parse_pow()
+ while self.stream.current.type == 'mod':
+ next(self.stream)
+ right = self.parse_pow()
+ left = nodes.Mod(left, right, lineno=lineno)
+ lineno = self.stream.current.lineno
+ return left
+
+ def parse_pow(self):
+ lineno = self.stream.current.lineno
+ left = self.parse_unary()
+ while self.stream.current.type == 'pow':
+ next(self.stream)
+ right = self.parse_unary()
+ left = nodes.Pow(left, right, lineno=lineno)
+ lineno = self.stream.current.lineno
+ return left
+
+ def parse_unary(self, with_filter=True):
+ token_type = self.stream.current.type
+ lineno = self.stream.current.lineno
+ if token_type == 'sub':
+ next(self.stream)
+ node = nodes.Neg(self.parse_unary(False), lineno=lineno)
+ elif token_type == 'add':
+ next(self.stream)
+ node = nodes.Pos(self.parse_unary(False), lineno=lineno)
+ else:
+ node = self.parse_primary()
+ node = self.parse_postfix(node)
+ if with_filter:
+ node = self.parse_filter_expr(node)
+ return node
+
+ def parse_primary(self):
+ token = self.stream.current
+ if token.type == 'name':
+ if token.value in ('true', 'false', 'True', 'False'):
+ node = nodes.Const(token.value in ('true', 'True'),
+ lineno=token.lineno)
+ elif token.value in ('none', 'None'):
+ node = nodes.Const(None, lineno=token.lineno)
+ else:
+ node = nodes.Name(token.value, 'load', lineno=token.lineno)
+ next(self.stream)
+ elif token.type == 'string':
+ next(self.stream)
+ buf = [token.value]
+ lineno = token.lineno
+ while self.stream.current.type == 'string':
+ buf.append(self.stream.current.value)
+ next(self.stream)
+ node = nodes.Const(''.join(buf), lineno=lineno)
+ elif token.type in ('integer', 'float'):
+ next(self.stream)
+ node = nodes.Const(token.value, lineno=token.lineno)
+ elif token.type == 'lparen':
+ next(self.stream)
+ node = self.parse_tuple(explicit_parentheses=True)
+ self.stream.expect('rparen')
+ elif token.type == 'lbracket':
+ node = self.parse_list()
+ elif token.type == 'lbrace':
+ node = self.parse_dict()
+ else:
+ self.fail("unexpected '%s'" % describe_token(token), token.lineno)
+ return node
+
+ def parse_tuple(self, simplified=False, with_condexpr=True,
+ extra_end_rules=None, explicit_parentheses=False):
+ """Works like `parse_expression` but if multiple expressions are
+ delimited by a comma a :class:`~jinja2.nodes.Tuple` node is created.
+ This method could also return a regular expression instead of a tuple
+ if no commas where found.
+
+ The default parsing mode is a full tuple. If `simplified` is `True`
+ only names and literals are parsed. The `no_condexpr` parameter is
+ forwarded to :meth:`parse_expression`.
+
+ Because tuples do not require delimiters and may end in a bogus comma
+ an extra hint is needed that marks the end of a tuple. For example
+ for loops support tuples between `for` and `in`. In that case the
+ `extra_end_rules` is set to ``['name:in']``.
+
+ `explicit_parentheses` is true if the parsing was triggered by an
+ expression in parentheses. This is used to figure out if an empty
+ tuple is a valid expression or not.
+ """
+ lineno = self.stream.current.lineno
+ if simplified:
+ parse = self.parse_primary
+ elif with_condexpr:
+ parse = self.parse_expression
+ else:
+ parse = lambda: self.parse_expression(with_condexpr=False)
+ args = []
+ is_tuple = False
+ while 1:
+ if args:
+ self.stream.expect('comma')
+ if self.is_tuple_end(extra_end_rules):
+ break
+ args.append(parse())
+ if self.stream.current.type == 'comma':
+ is_tuple = True
+ else:
+ break
+ lineno = self.stream.current.lineno
+
+ if not is_tuple:
+ if args:
+ return args[0]
+
+ # if we don't have explicit parentheses, an empty tuple is
+ # not a valid expression. This would mean nothing (literally
+ # nothing) in the spot of an expression would be an empty
+ # tuple.
+ if not explicit_parentheses:
+ self.fail('Expected an expression, got \'%s\'' %
+ describe_token(self.stream.current))
+
+ return nodes.Tuple(args, 'load', lineno=lineno)
+
+ def parse_list(self):
+ token = self.stream.expect('lbracket')
+ items = []
+ while self.stream.current.type != 'rbracket':
+ if items:
+ self.stream.expect('comma')
+ if self.stream.current.type == 'rbracket':
+ break
+ items.append(self.parse_expression())
+ self.stream.expect('rbracket')
+ return nodes.List(items, lineno=token.lineno)
+
+ def parse_dict(self):
+ token = self.stream.expect('lbrace')
+ items = []
+ while self.stream.current.type != 'rbrace':
+ if items:
+ self.stream.expect('comma')
+ if self.stream.current.type == 'rbrace':
+ break
+ key = self.parse_expression()
+ self.stream.expect('colon')
+ value = self.parse_expression()
+ items.append(nodes.Pair(key, value, lineno=key.lineno))
+ self.stream.expect('rbrace')
+ return nodes.Dict(items, lineno=token.lineno)
+
+ def parse_postfix(self, node):
+ while 1:
+ token_type = self.stream.current.type
+ if token_type == 'dot' or token_type == 'lbracket':
+ node = self.parse_subscript(node)
+ # calls are valid both after postfix expressions (getattr
+ # and getitem) as well as filters and tests
+ elif token_type == 'lparen':
+ node = self.parse_call(node)
+ else:
+ break
+ return node
+
+ def parse_filter_expr(self, node):
+ while 1:
+ token_type = self.stream.current.type
+ if token_type == 'pipe':
+ node = self.parse_filter(node)
+ elif token_type == 'name' and self.stream.current.value == 'is':
+ node = self.parse_test(node)
+ # calls are valid both after postfix expressions (getattr
+ # and getitem) as well as filters and tests
+ elif token_type == 'lparen':
+ node = self.parse_call(node)
+ else:
+ break
+ return node
+
+ def parse_subscript(self, node):
+ token = next(self.stream)
+ if token.type == 'dot':
+ attr_token = self.stream.current
+ next(self.stream)
+ if attr_token.type == 'name':
+ return nodes.Getattr(node, attr_token.value, 'load',
+ lineno=token.lineno)
+ elif attr_token.type != 'integer':
+ self.fail('expected name or number', attr_token.lineno)
+ arg = nodes.Const(attr_token.value, lineno=attr_token.lineno)
+ return nodes.Getitem(node, arg, 'load', lineno=token.lineno)
+ if token.type == 'lbracket':
+ args = []
+ while self.stream.current.type != 'rbracket':
+ if args:
+ self.stream.expect('comma')
+ args.append(self.parse_subscribed())
+ self.stream.expect('rbracket')
+ if len(args) == 1:
+ arg = args[0]
+ else:
+ arg = nodes.Tuple(args, 'load', lineno=token.lineno)
+ return nodes.Getitem(node, arg, 'load', lineno=token.lineno)
+ self.fail('expected subscript expression', self.lineno)
+
+ def parse_subscribed(self):
+ lineno = self.stream.current.lineno
+
+ if self.stream.current.type == 'colon':
+ next(self.stream)
+ args = [None]
+ else:
+ node = self.parse_expression()
+ if self.stream.current.type != 'colon':
+ return node
+ next(self.stream)
+ args = [node]
+
+ if self.stream.current.type == 'colon':
+ args.append(None)
+ elif self.stream.current.type not in ('rbracket', 'comma'):
+ args.append(self.parse_expression())
+ else:
+ args.append(None)
+
+ if self.stream.current.type == 'colon':
+ next(self.stream)
+ if self.stream.current.type not in ('rbracket', 'comma'):
+ args.append(self.parse_expression())
+ else:
+ args.append(None)
+ else:
+ args.append(None)
+
+ return nodes.Slice(lineno=lineno, *args)
+
+ def parse_call(self, node):
+ token = self.stream.expect('lparen')
+ args = []
+ kwargs = []
+ dyn_args = dyn_kwargs = None
+ require_comma = False
+
+ def ensure(expr):
+ if not expr:
+ self.fail('invalid syntax for function call expression',
+ token.lineno)
+
+ while self.stream.current.type != 'rparen':
+ if require_comma:
+ self.stream.expect('comma')
+ # support for trailing comma
+ if self.stream.current.type == 'rparen':
+ break
+ if self.stream.current.type == 'mul':
+ ensure(dyn_args is None and dyn_kwargs is None)
+ next(self.stream)
+ dyn_args = self.parse_expression()
+ elif self.stream.current.type == 'pow':
+ ensure(dyn_kwargs is None)
+ next(self.stream)
+ dyn_kwargs = self.parse_expression()
+ else:
+ ensure(dyn_args is None and dyn_kwargs is None)
+ if self.stream.current.type == 'name' and \
+ self.stream.look().type == 'assign':
+ key = self.stream.current.value
+ self.stream.skip(2)
+ value = self.parse_expression()
+ kwargs.append(nodes.Keyword(key, value,
+ lineno=value.lineno))
+ else:
+ ensure(not kwargs)
+ args.append(self.parse_expression())
+
+ require_comma = True
+ self.stream.expect('rparen')
+
+ if node is None:
+ return args, kwargs, dyn_args, dyn_kwargs
+ return nodes.Call(node, args, kwargs, dyn_args, dyn_kwargs,
+ lineno=token.lineno)
+
+ def parse_filter(self, node, start_inline=False):
+ while self.stream.current.type == 'pipe' or start_inline:
+ if not start_inline:
+ next(self.stream)
+ token = self.stream.expect('name')
+ name = token.value
+ while self.stream.current.type == 'dot':
+ next(self.stream)
+ name += '.' + self.stream.expect('name').value
+ if self.stream.current.type == 'lparen':
+ args, kwargs, dyn_args, dyn_kwargs = self.parse_call(None)
+ else:
+ args = []
+ kwargs = []
+ dyn_args = dyn_kwargs = None
+ node = nodes.Filter(node, name, args, kwargs, dyn_args,
+ dyn_kwargs, lineno=token.lineno)
+ start_inline = False
+ return node
+
+ def parse_test(self, node):
+ token = next(self.stream)
+ if self.stream.current.test('name:not'):
+ next(self.stream)
+ negated = True
+ else:
+ negated = False
+ name = self.stream.expect('name').value
+ while self.stream.current.type == 'dot':
+ next(self.stream)
+ name += '.' + self.stream.expect('name').value
+ dyn_args = dyn_kwargs = None
+ kwargs = []
+ if self.stream.current.type == 'lparen':
+ args, kwargs, dyn_args, dyn_kwargs = self.parse_call(None)
+ elif (self.stream.current.type in ('name', 'string', 'integer',
+ 'float', 'lparen', 'lbracket',
+ 'lbrace') and not
+ self.stream.current.test_any('name:else', 'name:or',
+ 'name:and')):
+ if self.stream.current.test('name:is'):
+ self.fail('You cannot chain multiple tests with is')
+ args = [self.parse_expression()]
+ else:
+ args = []
+ node = nodes.Test(node, name, args, kwargs, dyn_args,
+ dyn_kwargs, lineno=token.lineno)
+ if negated:
+ node = nodes.Not(node, lineno=token.lineno)
+ return node
+
+ def subparse(self, end_tokens=None):
+ body = []
+ data_buffer = []
+ add_data = data_buffer.append
+
+ if end_tokens is not None:
+ self._end_token_stack.append(end_tokens)
+
+ def flush_data():
+ if data_buffer:
+ lineno = data_buffer[0].lineno
+ body.append(nodes.Output(data_buffer[:], lineno=lineno))
+ del data_buffer[:]
+
+ try:
+ while self.stream:
+ token = self.stream.current
+ if token.type == 'data':
+ if token.value:
+ add_data(nodes.TemplateData(token.value,
+ lineno=token.lineno))
+ next(self.stream)
+ elif token.type == 'variable_begin':
+ next(self.stream)
+ add_data(self.parse_tuple(with_condexpr=True))
+ self.stream.expect('variable_end')
+ elif token.type == 'block_begin':
+ flush_data()
+ next(self.stream)
+ if end_tokens is not None and \
+ self.stream.current.test_any(*end_tokens):
+ return body
+ rv = self.parse_statement()
+ if isinstance(rv, list):
+ body.extend(rv)
+ else:
+ body.append(rv)
+ self.stream.expect('block_end')
+ else:
+ raise AssertionError('internal parsing error')
+
+ flush_data()
+ finally:
+ if end_tokens is not None:
+ self._end_token_stack.pop()
+
+ return body
+
+ def parse(self):
+ """Parse the whole template into a `Template` node."""
+ result = nodes.Template(self.subparse(), lineno=1)
+ result.set_environment(self.environment)
+ return result
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/runtime.py b/deps/v8_inspector/deps/jinja2/jinja2/runtime.py
new file mode 100644
index 0000000000..685a12da06
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/runtime.py
@@ -0,0 +1,667 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.runtime
+ ~~~~~~~~~~~~~~
+
+ Runtime helpers.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD.
+"""
+import sys
+
+from itertools import chain
+from jinja2.nodes import EvalContext, _context_function_types
+from jinja2.utils import Markup, soft_unicode, escape, missing, concat, \
+ internalcode, object_type_repr
+from jinja2.exceptions import UndefinedError, TemplateRuntimeError, \
+ TemplateNotFound
+from jinja2._compat import imap, text_type, iteritems, \
+ implements_iterator, implements_to_string, string_types, PY2
+
+
+# these variables are exported to the template runtime
+__all__ = ['LoopContext', 'TemplateReference', 'Macro', 'Markup',
+ 'TemplateRuntimeError', 'missing', 'concat', 'escape',
+ 'markup_join', 'unicode_join', 'to_string', 'identity',
+ 'TemplateNotFound', 'make_logging_undefined']
+
+#: the name of the function that is used to convert something into
+#: a string. We can just use the text type here.
+to_string = text_type
+
+#: the identity function. Useful for certain things in the environment
+identity = lambda x: x
+
+_last_iteration = object()
+
+
+def markup_join(seq):
+ """Concatenation that escapes if necessary and converts to unicode."""
+ buf = []
+ iterator = imap(soft_unicode, seq)
+ for arg in iterator:
+ buf.append(arg)
+ if hasattr(arg, '__html__'):
+ return Markup(u'').join(chain(buf, iterator))
+ return concat(buf)
+
+
+def unicode_join(seq):
+ """Simple args to unicode conversion and concatenation."""
+ return concat(imap(text_type, seq))
+
+
+def new_context(environment, template_name, blocks, vars=None,
+ shared=None, globals=None, locals=None):
+ """Internal helper to for context creation."""
+ if vars is None:
+ vars = {}
+ if shared:
+ parent = vars
+ else:
+ parent = dict(globals or (), **vars)
+ if locals:
+ # if the parent is shared a copy should be created because
+ # we don't want to modify the dict passed
+ if shared:
+ parent = dict(parent)
+ for key, value in iteritems(locals):
+ if key[:2] == 'l_' and value is not missing:
+ parent[key[2:]] = value
+ return environment.context_class(environment, parent, template_name,
+ blocks)
+
+
+class TemplateReference(object):
+ """The `self` in templates."""
+
+ def __init__(self, context):
+ self.__context = context
+
+ def __getitem__(self, name):
+ blocks = self.__context.blocks[name]
+ return BlockReference(name, self.__context, blocks, 0)
+
+ def __repr__(self):
+ return '<%s %r>' % (
+ self.__class__.__name__,
+ self.__context.name
+ )
+
+
+class Context(object):
+ """The template context holds the variables of a template. It stores the
+ values passed to the template and also the names the template exports.
+ Creating instances is neither supported nor useful as it's created
+ automatically at various stages of the template evaluation and should not
+ be created by hand.
+
+ The context is immutable. Modifications on :attr:`parent` **must not**
+ happen and modifications on :attr:`vars` are allowed from generated
+ template code only. Template filters and global functions marked as
+ :func:`contextfunction`\s get the active context passed as first argument
+ and are allowed to access the context read-only.
+
+ The template context supports read only dict operations (`get`,
+ `keys`, `values`, `items`, `iterkeys`, `itervalues`, `iteritems`,
+ `__getitem__`, `__contains__`). Additionally there is a :meth:`resolve`
+ method that doesn't fail with a `KeyError` but returns an
+ :class:`Undefined` object for missing variables.
+ """
+ __slots__ = ('parent', 'vars', 'environment', 'eval_ctx', 'exported_vars',
+ 'name', 'blocks', '__weakref__')
+
+ def __init__(self, environment, parent, name, blocks):
+ self.parent = parent
+ self.vars = {}
+ self.environment = environment
+ self.eval_ctx = EvalContext(self.environment, name)
+ self.exported_vars = set()
+ self.name = name
+
+ # create the initial mapping of blocks. Whenever template inheritance
+ # takes place the runtime will update this mapping with the new blocks
+ # from the template.
+ self.blocks = dict((k, [v]) for k, v in iteritems(blocks))
+
+ def super(self, name, current):
+ """Render a parent block."""
+ try:
+ blocks = self.blocks[name]
+ index = blocks.index(current) + 1
+ blocks[index]
+ except LookupError:
+ return self.environment.undefined('there is no parent block '
+ 'called %r.' % name,
+ name='super')
+ return BlockReference(name, self, blocks, index)
+
+ def get(self, key, default=None):
+ """Returns an item from the template context, if it doesn't exist
+ `default` is returned.
+ """
+ try:
+ return self[key]
+ except KeyError:
+ return default
+
+ def resolve(self, key):
+ """Looks up a variable like `__getitem__` or `get` but returns an
+ :class:`Undefined` object with the name of the name looked up.
+ """
+ if key in self.vars:
+ return self.vars[key]
+ if key in self.parent:
+ return self.parent[key]
+ return self.environment.undefined(name=key)
+
+ def get_exported(self):
+ """Get a new dict with the exported variables."""
+ return dict((k, self.vars[k]) for k in self.exported_vars)
+
+ def get_all(self):
+ """Return a copy of the complete context as dict including the
+ exported variables.
+ """
+ return dict(self.parent, **self.vars)
+
+ @internalcode
+ def call(__self, __obj, *args, **kwargs):
+ """Call the callable with the arguments and keyword arguments
+ provided but inject the active context or environment as first
+ argument if the callable is a :func:`contextfunction` or
+ :func:`environmentfunction`.
+ """
+ if __debug__:
+ __traceback_hide__ = True # noqa
+
+ # Allow callable classes to take a context
+ fn = __obj.__call__
+ for fn_type in ('contextfunction',
+ 'evalcontextfunction',
+ 'environmentfunction'):
+ if hasattr(fn, fn_type):
+ __obj = fn
+ break
+
+ if isinstance(__obj, _context_function_types):
+ if getattr(__obj, 'contextfunction', 0):
+ args = (__self,) + args
+ elif getattr(__obj, 'evalcontextfunction', 0):
+ args = (__self.eval_ctx,) + args
+ elif getattr(__obj, 'environmentfunction', 0):
+ args = (__self.environment,) + args
+ try:
+ return __obj(*args, **kwargs)
+ except StopIteration:
+ return __self.environment.undefined('value was undefined because '
+ 'a callable raised a '
+ 'StopIteration exception')
+
+ def derived(self, locals=None):
+ """Internal helper function to create a derived context."""
+ context = new_context(self.environment, self.name, {},
+ self.parent, True, None, locals)
+ context.vars.update(self.vars)
+ context.eval_ctx = self.eval_ctx
+ context.blocks.update((k, list(v)) for k, v in iteritems(self.blocks))
+ return context
+
+ def _all(meth):
+ proxy = lambda self: getattr(self.get_all(), meth)()
+ proxy.__doc__ = getattr(dict, meth).__doc__
+ proxy.__name__ = meth
+ return proxy
+
+ keys = _all('keys')
+ values = _all('values')
+ items = _all('items')
+
+ # not available on python 3
+ if PY2:
+ iterkeys = _all('iterkeys')
+ itervalues = _all('itervalues')
+ iteritems = _all('iteritems')
+ del _all
+
+ def __contains__(self, name):
+ return name in self.vars or name in self.parent
+
+ def __getitem__(self, key):
+ """Lookup a variable or raise `KeyError` if the variable is
+ undefined.
+ """
+ item = self.resolve(key)
+ if isinstance(item, Undefined):
+ raise KeyError(key)
+ return item
+
+ def __repr__(self):
+ return '<%s %s of %r>' % (
+ self.__class__.__name__,
+ repr(self.get_all()),
+ self.name
+ )
+
+
+# register the context as mapping if possible
+try:
+ from collections import Mapping
+ Mapping.register(Context)
+except ImportError:
+ pass
+
+
+class BlockReference(object):
+ """One block on a template reference."""
+
+ def __init__(self, name, context, stack, depth):
+ self.name = name
+ self._context = context
+ self._stack = stack
+ self._depth = depth
+
+ @property
+ def super(self):
+ """Super the block."""
+ if self._depth + 1 >= len(self._stack):
+ return self._context.environment. \
+ undefined('there is no parent block called %r.' %
+ self.name, name='super')
+ return BlockReference(self.name, self._context, self._stack,
+ self._depth + 1)
+
+ @internalcode
+ def __call__(self):
+ rv = concat(self._stack[self._depth](self._context))
+ if self._context.eval_ctx.autoescape:
+ rv = Markup(rv)
+ return rv
+
+
+class LoopContext(object):
+ """A loop context for dynamic iteration."""
+
+ def __init__(self, iterable, recurse=None, depth0=0):
+ self._iterator = iter(iterable)
+ self._recurse = recurse
+ self._after = self._safe_next()
+ self.index0 = -1
+ self.depth0 = depth0
+
+ # try to get the length of the iterable early. This must be done
+ # here because there are some broken iterators around where there
+ # __len__ is the number of iterations left (i'm looking at your
+ # listreverseiterator!).
+ try:
+ self._length = len(iterable)
+ except (TypeError, AttributeError):
+ self._length = None
+
+ def cycle(self, *args):
+ """Cycles among the arguments with the current loop index."""
+ if not args:
+ raise TypeError('no items for cycling given')
+ return args[self.index0 % len(args)]
+
+ first = property(lambda x: x.index0 == 0)
+ last = property(lambda x: x._after is _last_iteration)
+ index = property(lambda x: x.index0 + 1)
+ revindex = property(lambda x: x.length - x.index0)
+ revindex0 = property(lambda x: x.length - x.index)
+ depth = property(lambda x: x.depth0 + 1)
+
+ def __len__(self):
+ return self.length
+
+ def __iter__(self):
+ return LoopContextIterator(self)
+
+ def _safe_next(self):
+ try:
+ return next(self._iterator)
+ except StopIteration:
+ return _last_iteration
+
+ @internalcode
+ def loop(self, iterable):
+ if self._recurse is None:
+ raise TypeError('Tried to call non recursive loop. Maybe you '
+ "forgot the 'recursive' modifier.")
+ return self._recurse(iterable, self._recurse, self.depth0 + 1)
+
+ # a nifty trick to enhance the error message if someone tried to call
+ # the the loop without or with too many arguments.
+ __call__ = loop
+ del loop
+
+ @property
+ def length(self):
+ if self._length is None:
+ # if was not possible to get the length of the iterator when
+ # the loop context was created (ie: iterating over a generator)
+ # we have to convert the iterable into a sequence and use the
+ # length of that + the number of iterations so far.
+ iterable = tuple(self._iterator)
+ self._iterator = iter(iterable)
+ iterations_done = self.index0 + 2
+ self._length = len(iterable) + iterations_done
+ return self._length
+
+ def __repr__(self):
+ return '<%s %r/%r>' % (
+ self.__class__.__name__,
+ self.index,
+ self.length
+ )
+
+
+@implements_iterator
+class LoopContextIterator(object):
+ """The iterator for a loop context."""
+ __slots__ = ('context',)
+
+ def __init__(self, context):
+ self.context = context
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ ctx = self.context
+ ctx.index0 += 1
+ if ctx._after is _last_iteration:
+ raise StopIteration()
+ next_elem = ctx._after
+ ctx._after = ctx._safe_next()
+ return next_elem, ctx
+
+
+class Macro(object):
+ """Wraps a macro function."""
+
+ def __init__(self, environment, func, name, arguments, defaults,
+ catch_kwargs, catch_varargs, caller):
+ self._environment = environment
+ self._func = func
+ self._argument_count = len(arguments)
+ self.name = name
+ self.arguments = arguments
+ self.defaults = defaults
+ self.catch_kwargs = catch_kwargs
+ self.catch_varargs = catch_varargs
+ self.caller = caller
+
+ @internalcode
+ def __call__(self, *args, **kwargs):
+ # try to consume the positional arguments
+ arguments = list(args[:self._argument_count])
+ off = len(arguments)
+
+ # if the number of arguments consumed is not the number of
+ # arguments expected we start filling in keyword arguments
+ # and defaults.
+ if off != self._argument_count:
+ for idx, name in enumerate(self.arguments[len(arguments):]):
+ try:
+ value = kwargs.pop(name)
+ except KeyError:
+ try:
+ value = self.defaults[idx - self._argument_count + off]
+ except IndexError:
+ value = self._environment.undefined(
+ 'parameter %r was not provided' % name, name=name)
+ arguments.append(value)
+
+ # it's important that the order of these arguments does not change
+ # if not also changed in the compiler's `function_scoping` method.
+ # the order is caller, keyword arguments, positional arguments!
+ if self.caller:
+ caller = kwargs.pop('caller', None)
+ if caller is None:
+ caller = self._environment.undefined('No caller defined',
+ name='caller')
+ arguments.append(caller)
+ if self.catch_kwargs:
+ arguments.append(kwargs)
+ elif kwargs:
+ raise TypeError('macro %r takes no keyword argument %r' %
+ (self.name, next(iter(kwargs))))
+ if self.catch_varargs:
+ arguments.append(args[self._argument_count:])
+ elif len(args) > self._argument_count:
+ raise TypeError('macro %r takes not more than %d argument(s)' %
+ (self.name, len(self.arguments)))
+ return self._func(*arguments)
+
+ def __repr__(self):
+ return '<%s %s>' % (
+ self.__class__.__name__,
+ self.name is None and 'anonymous' or repr(self.name)
+ )
+
+
+@implements_to_string
+class Undefined(object):
+ """The default undefined type. This undefined type can be printed and
+ iterated over, but every other access will raise an :exc:`jinja2.exceptions.UndefinedError`:
+
+ >>> foo = Undefined(name='foo')
+ >>> str(foo)
+ ''
+ >>> not foo
+ True
+ >>> foo + 42
+ Traceback (most recent call last):
+ ...
+ jinja2.exceptions.UndefinedError: 'foo' is undefined
+ """
+ __slots__ = ('_undefined_hint', '_undefined_obj', '_undefined_name',
+ '_undefined_exception')
+
+ def __init__(self, hint=None, obj=missing, name=None, exc=UndefinedError):
+ self._undefined_hint = hint
+ self._undefined_obj = obj
+ self._undefined_name = name
+ self._undefined_exception = exc
+
+ @internalcode
+ def _fail_with_undefined_error(self, *args, **kwargs):
+ """Regular callback function for undefined objects that raises an
+ `jinja2.exceptions.UndefinedError` on call.
+ """
+ if self._undefined_hint is None:
+ if self._undefined_obj is missing:
+ hint = '%r is undefined' % self._undefined_name
+ elif not isinstance(self._undefined_name, string_types):
+ hint = '%s has no element %r' % (
+ object_type_repr(self._undefined_obj),
+ self._undefined_name
+ )
+ else:
+ hint = '%r has no attribute %r' % (
+ object_type_repr(self._undefined_obj),
+ self._undefined_name
+ )
+ else:
+ hint = self._undefined_hint
+ raise self._undefined_exception(hint)
+
+ @internalcode
+ def __getattr__(self, name):
+ if name[:2] == '__':
+ raise AttributeError(name)
+ return self._fail_with_undefined_error()
+
+ __add__ = __radd__ = __mul__ = __rmul__ = __div__ = __rdiv__ = \
+ __truediv__ = __rtruediv__ = __floordiv__ = __rfloordiv__ = \
+ __mod__ = __rmod__ = __pos__ = __neg__ = __call__ = \
+ __getitem__ = __lt__ = __le__ = __gt__ = __ge__ = __int__ = \
+ __float__ = __complex__ = __pow__ = __rpow__ = \
+ _fail_with_undefined_error
+
+ def __eq__(self, other):
+ return type(self) is type(other)
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def __hash__(self):
+ return id(type(self))
+
+ def __str__(self):
+ return u''
+
+ def __len__(self):
+ return 0
+
+ def __iter__(self):
+ if 0:
+ yield None
+
+ def __nonzero__(self):
+ return False
+ __bool__ = __nonzero__
+
+ def __repr__(self):
+ return 'Undefined'
+
+
+def make_logging_undefined(logger=None, base=None):
+ """Given a logger object this returns a new undefined class that will
+ log certain failures. It will log iterations and printing. If no
+ logger is given a default logger is created.
+
+ Example::
+
+ logger = logging.getLogger(__name__)
+ LoggingUndefined = make_logging_undefined(
+ logger=logger,
+ base=Undefined
+ )
+
+ .. versionadded:: 2.8
+
+ :param logger: the logger to use. If not provided, a default logger
+ is created.
+ :param base: the base class to add logging functionality to. This
+ defaults to :class:`Undefined`.
+ """
+ if logger is None:
+ import logging
+ logger = logging.getLogger(__name__)
+ logger.addHandler(logging.StreamHandler(sys.stderr))
+ if base is None:
+ base = Undefined
+
+ def _log_message(undef):
+ if undef._undefined_hint is None:
+ if undef._undefined_obj is missing:
+ hint = '%s is undefined' % undef._undefined_name
+ elif not isinstance(undef._undefined_name, string_types):
+ hint = '%s has no element %s' % (
+ object_type_repr(undef._undefined_obj),
+ undef._undefined_name)
+ else:
+ hint = '%s has no attribute %s' % (
+ object_type_repr(undef._undefined_obj),
+ undef._undefined_name)
+ else:
+ hint = undef._undefined_hint
+ logger.warning('Template variable warning: %s', hint)
+
+ class LoggingUndefined(base):
+
+ def _fail_with_undefined_error(self, *args, **kwargs):
+ try:
+ return base._fail_with_undefined_error(self, *args, **kwargs)
+ except self._undefined_exception as e:
+ logger.error('Template variable error: %s', str(e))
+ raise e
+
+ def __str__(self):
+ rv = base.__str__(self)
+ _log_message(self)
+ return rv
+
+ def __iter__(self):
+ rv = base.__iter__(self)
+ _log_message(self)
+ return rv
+
+ if PY2:
+ def __nonzero__(self):
+ rv = base.__nonzero__(self)
+ _log_message(self)
+ return rv
+
+ def __unicode__(self):
+ rv = base.__unicode__(self)
+ _log_message(self)
+ return rv
+ else:
+ def __bool__(self):
+ rv = base.__bool__(self)
+ _log_message(self)
+ return rv
+
+ return LoggingUndefined
+
+
+@implements_to_string
+class DebugUndefined(Undefined):
+ """An undefined that returns the debug info when printed.
+
+ >>> foo = DebugUndefined(name='foo')
+ >>> str(foo)
+ '{{ foo }}'
+ >>> not foo
+ True
+ >>> foo + 42
+ Traceback (most recent call last):
+ ...
+ jinja2.exceptions.UndefinedError: 'foo' is undefined
+ """
+ __slots__ = ()
+
+ def __str__(self):
+ if self._undefined_hint is None:
+ if self._undefined_obj is missing:
+ return u'{{ %s }}' % self._undefined_name
+ return '{{ no such element: %s[%r] }}' % (
+ object_type_repr(self._undefined_obj),
+ self._undefined_name
+ )
+ return u'{{ undefined value printed: %s }}' % self._undefined_hint
+
+
+@implements_to_string
+class StrictUndefined(Undefined):
+ """An undefined that barks on print and iteration as well as boolean
+ tests and all kinds of comparisons. In other words: you can do nothing
+ with it except checking if it's defined using the `defined` test.
+
+ >>> foo = StrictUndefined(name='foo')
+ >>> str(foo)
+ Traceback (most recent call last):
+ ...
+ jinja2.exceptions.UndefinedError: 'foo' is undefined
+ >>> not foo
+ Traceback (most recent call last):
+ ...
+ jinja2.exceptions.UndefinedError: 'foo' is undefined
+ >>> foo + 42
+ Traceback (most recent call last):
+ ...
+ jinja2.exceptions.UndefinedError: 'foo' is undefined
+ """
+ __slots__ = ()
+ __iter__ = __str__ = __len__ = __nonzero__ = __eq__ = \
+ __ne__ = __bool__ = __hash__ = \
+ Undefined._fail_with_undefined_error
+
+
+# remove remaining slots attributes, after the metaclass did the magic they
+# are unneeded and irritating as they contain wrong data for the subclasses.
+del Undefined.__slots__, DebugUndefined.__slots__, StrictUndefined.__slots__
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/sandbox.py b/deps/v8_inspector/deps/jinja2/jinja2/sandbox.py
new file mode 100644
index 0000000000..8b491e7c3c
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/sandbox.py
@@ -0,0 +1,367 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.sandbox
+ ~~~~~~~~~~~~~~
+
+ Adds a sandbox layer to Jinja as it was the default behavior in the old
+ Jinja 1 releases. This sandbox is slightly different from Jinja 1 as the
+ default behavior is easier to use.
+
+ The behavior can be changed by subclassing the environment.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD.
+"""
+import types
+import operator
+from jinja2.environment import Environment
+from jinja2.exceptions import SecurityError
+from jinja2._compat import string_types, PY2
+
+
+#: maximum number of items a range may produce
+MAX_RANGE = 100000
+
+#: attributes of function objects that are considered unsafe.
+if PY2:
+ UNSAFE_FUNCTION_ATTRIBUTES = set(['func_closure', 'func_code', 'func_dict',
+ 'func_defaults', 'func_globals'])
+else:
+ # On versions > python 2 the special attributes on functions are gone,
+ # but they remain on methods and generators for whatever reason.
+ UNSAFE_FUNCTION_ATTRIBUTES = set()
+
+
+#: unsafe method attributes. function attributes are unsafe for methods too
+UNSAFE_METHOD_ATTRIBUTES = set(['im_class', 'im_func', 'im_self'])
+
+#: unsafe generator attirbutes.
+UNSAFE_GENERATOR_ATTRIBUTES = set(['gi_frame', 'gi_code'])
+
+import warnings
+
+# make sure we don't warn in python 2.6 about stuff we don't care about
+warnings.filterwarnings('ignore', 'the sets module', DeprecationWarning,
+ module='jinja2.sandbox')
+
+from collections import deque
+
+_mutable_set_types = (set,)
+_mutable_mapping_types = (dict,)
+_mutable_sequence_types = (list,)
+
+
+# on python 2.x we can register the user collection types
+try:
+ from UserDict import UserDict, DictMixin
+ from UserList import UserList
+ _mutable_mapping_types += (UserDict, DictMixin)
+ _mutable_set_types += (UserList,)
+except ImportError:
+ pass
+
+# if sets is still available, register the mutable set from there as well
+try:
+ from sets import Set
+ _mutable_set_types += (Set,)
+except ImportError:
+ pass
+
+#: register Python 2.6 abstract base classes
+try:
+ from collections import MutableSet, MutableMapping, MutableSequence
+ _mutable_set_types += (MutableSet,)
+ _mutable_mapping_types += (MutableMapping,)
+ _mutable_sequence_types += (MutableSequence,)
+except ImportError:
+ pass
+
+_mutable_spec = (
+ (_mutable_set_types, frozenset([
+ 'add', 'clear', 'difference_update', 'discard', 'pop', 'remove',
+ 'symmetric_difference_update', 'update'
+ ])),
+ (_mutable_mapping_types, frozenset([
+ 'clear', 'pop', 'popitem', 'setdefault', 'update'
+ ])),
+ (_mutable_sequence_types, frozenset([
+ 'append', 'reverse', 'insert', 'sort', 'extend', 'remove'
+ ])),
+ (deque, frozenset([
+ 'append', 'appendleft', 'clear', 'extend', 'extendleft', 'pop',
+ 'popleft', 'remove', 'rotate'
+ ]))
+)
+
+
+def safe_range(*args):
+ """A range that can't generate ranges with a length of more than
+ MAX_RANGE items.
+ """
+ rng = range(*args)
+ if len(rng) > MAX_RANGE:
+ raise OverflowError('range too big, maximum size for range is %d' %
+ MAX_RANGE)
+ return rng
+
+
+def unsafe(f):
+ """Marks a function or method as unsafe.
+
+ ::
+
+ @unsafe
+ def delete(self):
+ pass
+ """
+ f.unsafe_callable = True
+ return f
+
+
+def is_internal_attribute(obj, attr):
+ """Test if the attribute given is an internal python attribute. For
+ example this function returns `True` for the `func_code` attribute of
+ python objects. This is useful if the environment method
+ :meth:`~SandboxedEnvironment.is_safe_attribute` is overridden.
+
+ >>> from jinja2.sandbox import is_internal_attribute
+ >>> is_internal_attribute(str, "mro")
+ True
+ >>> is_internal_attribute(str, "upper")
+ False
+ """
+ if isinstance(obj, types.FunctionType):
+ if attr in UNSAFE_FUNCTION_ATTRIBUTES:
+ return True
+ elif isinstance(obj, types.MethodType):
+ if attr in UNSAFE_FUNCTION_ATTRIBUTES or \
+ attr in UNSAFE_METHOD_ATTRIBUTES:
+ return True
+ elif isinstance(obj, type):
+ if attr == 'mro':
+ return True
+ elif isinstance(obj, (types.CodeType, types.TracebackType, types.FrameType)):
+ return True
+ elif isinstance(obj, types.GeneratorType):
+ if attr in UNSAFE_GENERATOR_ATTRIBUTES:
+ return True
+ return attr.startswith('__')
+
+
+def modifies_known_mutable(obj, attr):
+ """This function checks if an attribute on a builtin mutable object
+ (list, dict, set or deque) would modify it if called. It also supports
+ the "user"-versions of the objects (`sets.Set`, `UserDict.*` etc.) and
+ with Python 2.6 onwards the abstract base classes `MutableSet`,
+ `MutableMapping`, and `MutableSequence`.
+
+ >>> modifies_known_mutable({}, "clear")
+ True
+ >>> modifies_known_mutable({}, "keys")
+ False
+ >>> modifies_known_mutable([], "append")
+ True
+ >>> modifies_known_mutable([], "index")
+ False
+
+ If called with an unsupported object (such as unicode) `False` is
+ returned.
+
+ >>> modifies_known_mutable("foo", "upper")
+ False
+ """
+ for typespec, unsafe in _mutable_spec:
+ if isinstance(obj, typespec):
+ return attr in unsafe
+ return False
+
+
+class SandboxedEnvironment(Environment):
+ """The sandboxed environment. It works like the regular environment but
+ tells the compiler to generate sandboxed code. Additionally subclasses of
+ this environment may override the methods that tell the runtime what
+ attributes or functions are safe to access.
+
+ If the template tries to access insecure code a :exc:`SecurityError` is
+ raised. However also other exceptions may occur during the rendering so
+ the caller has to ensure that all exceptions are caught.
+ """
+ sandboxed = True
+
+ #: default callback table for the binary operators. A copy of this is
+ #: available on each instance of a sandboxed environment as
+ #: :attr:`binop_table`
+ default_binop_table = {
+ '+': operator.add,
+ '-': operator.sub,
+ '*': operator.mul,
+ '/': operator.truediv,
+ '//': operator.floordiv,
+ '**': operator.pow,
+ '%': operator.mod
+ }
+
+ #: default callback table for the unary operators. A copy of this is
+ #: available on each instance of a sandboxed environment as
+ #: :attr:`unop_table`
+ default_unop_table = {
+ '+': operator.pos,
+ '-': operator.neg
+ }
+
+ #: a set of binary operators that should be intercepted. Each operator
+ #: that is added to this set (empty by default) is delegated to the
+ #: :meth:`call_binop` method that will perform the operator. The default
+ #: operator callback is specified by :attr:`binop_table`.
+ #:
+ #: The following binary operators are interceptable:
+ #: ``//``, ``%``, ``+``, ``*``, ``-``, ``/``, and ``**``
+ #:
+ #: The default operation form the operator table corresponds to the
+ #: builtin function. Intercepted calls are always slower than the native
+ #: operator call, so make sure only to intercept the ones you are
+ #: interested in.
+ #:
+ #: .. versionadded:: 2.6
+ intercepted_binops = frozenset()
+
+ #: a set of unary operators that should be intercepted. Each operator
+ #: that is added to this set (empty by default) is delegated to the
+ #: :meth:`call_unop` method that will perform the operator. The default
+ #: operator callback is specified by :attr:`unop_table`.
+ #:
+ #: The following unary operators are interceptable: ``+``, ``-``
+ #:
+ #: The default operation form the operator table corresponds to the
+ #: builtin function. Intercepted calls are always slower than the native
+ #: operator call, so make sure only to intercept the ones you are
+ #: interested in.
+ #:
+ #: .. versionadded:: 2.6
+ intercepted_unops = frozenset()
+
+ def intercept_unop(self, operator):
+ """Called during template compilation with the name of a unary
+ operator to check if it should be intercepted at runtime. If this
+ method returns `True`, :meth:`call_unop` is excuted for this unary
+ operator. The default implementation of :meth:`call_unop` will use
+ the :attr:`unop_table` dictionary to perform the operator with the
+ same logic as the builtin one.
+
+ The following unary operators are interceptable: ``+`` and ``-``
+
+ Intercepted calls are always slower than the native operator call,
+ so make sure only to intercept the ones you are interested in.
+
+ .. versionadded:: 2.6
+ """
+ return False
+
+
+ def __init__(self, *args, **kwargs):
+ Environment.__init__(self, *args, **kwargs)
+ self.globals['range'] = safe_range
+ self.binop_table = self.default_binop_table.copy()
+ self.unop_table = self.default_unop_table.copy()
+
+ def is_safe_attribute(self, obj, attr, value):
+ """The sandboxed environment will call this method to check if the
+ attribute of an object is safe to access. Per default all attributes
+ starting with an underscore are considered private as well as the
+ special attributes of internal python objects as returned by the
+ :func:`is_internal_attribute` function.
+ """
+ return not (attr.startswith('_') or is_internal_attribute(obj, attr))
+
+ def is_safe_callable(self, obj):
+ """Check if an object is safely callable. Per default a function is
+ considered safe unless the `unsafe_callable` attribute exists and is
+ True. Override this method to alter the behavior, but this won't
+ affect the `unsafe` decorator from this module.
+ """
+ return not (getattr(obj, 'unsafe_callable', False) or
+ getattr(obj, 'alters_data', False))
+
+ def call_binop(self, context, operator, left, right):
+ """For intercepted binary operator calls (:meth:`intercepted_binops`)
+ this function is executed instead of the builtin operator. This can
+ be used to fine tune the behavior of certain operators.
+
+ .. versionadded:: 2.6
+ """
+ return self.binop_table[operator](left, right)
+
+ def call_unop(self, context, operator, arg):
+ """For intercepted unary operator calls (:meth:`intercepted_unops`)
+ this function is executed instead of the builtin operator. This can
+ be used to fine tune the behavior of certain operators.
+
+ .. versionadded:: 2.6
+ """
+ return self.unop_table[operator](arg)
+
+ def getitem(self, obj, argument):
+ """Subscribe an object from sandboxed code."""
+ try:
+ return obj[argument]
+ except (TypeError, LookupError):
+ if isinstance(argument, string_types):
+ try:
+ attr = str(argument)
+ except Exception:
+ pass
+ else:
+ try:
+ value = getattr(obj, attr)
+ except AttributeError:
+ pass
+ else:
+ if self.is_safe_attribute(obj, argument, value):
+ return value
+ return self.unsafe_undefined(obj, argument)
+ return self.undefined(obj=obj, name=argument)
+
+ def getattr(self, obj, attribute):
+ """Subscribe an object from sandboxed code and prefer the
+ attribute. The attribute passed *must* be a bytestring.
+ """
+ try:
+ value = getattr(obj, attribute)
+ except AttributeError:
+ try:
+ return obj[attribute]
+ except (TypeError, LookupError):
+ pass
+ else:
+ if self.is_safe_attribute(obj, attribute, value):
+ return value
+ return self.unsafe_undefined(obj, attribute)
+ return self.undefined(obj=obj, name=attribute)
+
+ def unsafe_undefined(self, obj, attribute):
+ """Return an undefined object for unsafe attributes."""
+ return self.undefined('access to attribute %r of %r '
+ 'object is unsafe.' % (
+ attribute,
+ obj.__class__.__name__
+ ), name=attribute, obj=obj, exc=SecurityError)
+
+ def call(__self, __context, __obj, *args, **kwargs):
+ """Call an object from sandboxed code."""
+ # the double prefixes are to avoid double keyword argument
+ # errors when proxying the call.
+ if not __self.is_safe_callable(__obj):
+ raise SecurityError('%r is not safely callable' % (__obj,))
+ return __context.call(__obj, *args, **kwargs)
+
+
+class ImmutableSandboxedEnvironment(SandboxedEnvironment):
+ """Works exactly like the regular `SandboxedEnvironment` but does not
+ permit modifications on the builtin mutable objects `list`, `set`, and
+ `dict` by using the :func:`modifies_known_mutable` function.
+ """
+
+ def is_safe_attribute(self, obj, attr, value):
+ if not SandboxedEnvironment.is_safe_attribute(self, obj, attr, value):
+ return False
+ return not modifies_known_mutable(obj, attr)
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/tests.py b/deps/v8_inspector/deps/jinja2/jinja2/tests.py
new file mode 100644
index 0000000000..bb32349df0
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/tests.py
@@ -0,0 +1,173 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.tests
+ ~~~~~~~~~~~~
+
+ Jinja test functions. Used with the "is" operator.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import re
+from collections import Mapping
+from jinja2.runtime import Undefined
+from jinja2._compat import text_type, string_types, integer_types
+import decimal
+
+number_re = re.compile(r'^-?\d+(\.\d+)?$')
+regex_type = type(number_re)
+
+
+test_callable = callable
+
+
+def test_odd(value):
+ """Return true if the variable is odd."""
+ return value % 2 == 1
+
+
+def test_even(value):
+ """Return true if the variable is even."""
+ return value % 2 == 0
+
+
+def test_divisibleby(value, num):
+ """Check if a variable is divisible by a number."""
+ return value % num == 0
+
+
+def test_defined(value):
+ """Return true if the variable is defined:
+
+ .. sourcecode:: jinja
+
+ {% if variable is defined %}
+ value of variable: {{ variable }}
+ {% else %}
+ variable is not defined
+ {% endif %}
+
+ See the :func:`default` filter for a simple way to set undefined
+ variables.
+ """
+ return not isinstance(value, Undefined)
+
+
+def test_undefined(value):
+ """Like :func:`defined` but the other way round."""
+ return isinstance(value, Undefined)
+
+
+def test_none(value):
+ """Return true if the variable is none."""
+ return value is None
+
+
+def test_lower(value):
+ """Return true if the variable is lowercased."""
+ return text_type(value).islower()
+
+
+def test_upper(value):
+ """Return true if the variable is uppercased."""
+ return text_type(value).isupper()
+
+
+def test_string(value):
+ """Return true if the object is a string."""
+ return isinstance(value, string_types)
+
+
+def test_mapping(value):
+ """Return true if the object is a mapping (dict etc.).
+
+ .. versionadded:: 2.6
+ """
+ return isinstance(value, Mapping)
+
+
+def test_number(value):
+ """Return true if the variable is a number."""
+ return isinstance(value, integer_types + (float, complex, decimal.Decimal))
+
+
+def test_sequence(value):
+ """Return true if the variable is a sequence. Sequences are variables
+ that are iterable.
+ """
+ try:
+ len(value)
+ value.__getitem__
+ except:
+ return False
+ return True
+
+
+def test_equalto(value, other):
+ """Check if an object has the same value as another object:
+
+ .. sourcecode:: jinja
+
+ {% if foo.expression is equalto 42 %}
+ the foo attribute evaluates to the constant 42
+ {% endif %}
+
+ This appears to be a useless test as it does exactly the same as the
+ ``==`` operator, but it can be useful when used together with the
+ `selectattr` function:
+
+ .. sourcecode:: jinja
+
+ {{ users|selectattr("email", "equalto", "foo@bar.invalid") }}
+
+ .. versionadded:: 2.8
+ """
+ return value == other
+
+
+def test_sameas(value, other):
+ """Check if an object points to the same memory address than another
+ object:
+
+ .. sourcecode:: jinja
+
+ {% if foo.attribute is sameas false %}
+ the foo attribute really is the `False` singleton
+ {% endif %}
+ """
+ return value is other
+
+
+def test_iterable(value):
+ """Check if it's possible to iterate over an object."""
+ try:
+ iter(value)
+ except TypeError:
+ return False
+ return True
+
+
+def test_escaped(value):
+ """Check if the value is escaped."""
+ return hasattr(value, '__html__')
+
+
+TESTS = {
+ 'odd': test_odd,
+ 'even': test_even,
+ 'divisibleby': test_divisibleby,
+ 'defined': test_defined,
+ 'undefined': test_undefined,
+ 'none': test_none,
+ 'lower': test_lower,
+ 'upper': test_upper,
+ 'string': test_string,
+ 'mapping': test_mapping,
+ 'number': test_number,
+ 'sequence': test_sequence,
+ 'iterable': test_iterable,
+ 'callable': test_callable,
+ 'sameas': test_sameas,
+ 'equalto': test_equalto,
+ 'escaped': test_escaped
+}
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/utils.py b/deps/v8_inspector/deps/jinja2/jinja2/utils.py
new file mode 100644
index 0000000000..612d5c3d8b
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/utils.py
@@ -0,0 +1,531 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.utils
+ ~~~~~~~~~~~~
+
+ Utility functions.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import re
+import errno
+from collections import deque
+from threading import Lock
+from jinja2._compat import text_type, string_types, implements_iterator, \
+ url_quote
+
+
+_word_split_re = re.compile(r'(\s+)')
+_punctuation_re = re.compile(
+ '^(?P<lead>(?:%s)*)(?P<middle>.*?)(?P<trail>(?:%s)*)$' % (
+ '|'.join(map(re.escape, ('(', '<', '&lt;'))),
+ '|'.join(map(re.escape, ('.', ',', ')', '>', '\n', '&gt;')))
+ )
+)
+_simple_email_re = re.compile(r'^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$')
+_striptags_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
+_entity_re = re.compile(r'&([^;]+);')
+_letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+_digits = '0123456789'
+
+# special singleton representing missing values for the runtime
+missing = type('MissingType', (), {'__repr__': lambda x: 'missing'})()
+
+# internal code
+internal_code = set()
+
+concat = u''.join
+
+
+def contextfunction(f):
+ """This decorator can be used to mark a function or method context callable.
+ A context callable is passed the active :class:`Context` as first argument when
+ called from the template. This is useful if a function wants to get access
+ to the context or functions provided on the context object. For example
+ a function that returns a sorted list of template variables the current
+ template exports could look like this::
+
+ @contextfunction
+ def get_exported_names(context):
+ return sorted(context.exported_vars)
+ """
+ f.contextfunction = True
+ return f
+
+
+def evalcontextfunction(f):
+ """This decorator can be used to mark a function or method as an eval
+ context callable. This is similar to the :func:`contextfunction`
+ but instead of passing the context, an evaluation context object is
+ passed. For more information about the eval context, see
+ :ref:`eval-context`.
+
+ .. versionadded:: 2.4
+ """
+ f.evalcontextfunction = True
+ return f
+
+
+def environmentfunction(f):
+ """This decorator can be used to mark a function or method as environment
+ callable. This decorator works exactly like the :func:`contextfunction`
+ decorator just that the first argument is the active :class:`Environment`
+ and not context.
+ """
+ f.environmentfunction = True
+ return f
+
+
+def internalcode(f):
+ """Marks the function as internally used"""
+ internal_code.add(f.__code__)
+ return f
+
+
+def is_undefined(obj):
+ """Check if the object passed is undefined. This does nothing more than
+ performing an instance check against :class:`Undefined` but looks nicer.
+ This can be used for custom filters or tests that want to react to
+ undefined variables. For example a custom default filter can look like
+ this::
+
+ def default(var, default=''):
+ if is_undefined(var):
+ return default
+ return var
+ """
+ from jinja2.runtime import Undefined
+ return isinstance(obj, Undefined)
+
+
+def consume(iterable):
+ """Consumes an iterable without doing anything with it."""
+ for event in iterable:
+ pass
+
+
+def clear_caches():
+ """Jinja2 keeps internal caches for environments and lexers. These are
+ used so that Jinja2 doesn't have to recreate environments and lexers all
+ the time. Normally you don't have to care about that but if you are
+ messuring memory consumption you may want to clean the caches.
+ """
+ from jinja2.environment import _spontaneous_environments
+ from jinja2.lexer import _lexer_cache
+ _spontaneous_environments.clear()
+ _lexer_cache.clear()
+
+
+def import_string(import_name, silent=False):
+ """Imports an object based on a string. This is useful if you want to
+ use import paths as endpoints or something similar. An import path can
+ be specified either in dotted notation (``xml.sax.saxutils.escape``)
+ or with a colon as object delimiter (``xml.sax.saxutils:escape``).
+
+ If the `silent` is True the return value will be `None` if the import
+ fails.
+
+ :return: imported object
+ """
+ try:
+ if ':' in import_name:
+ module, obj = import_name.split(':', 1)
+ elif '.' in import_name:
+ items = import_name.split('.')
+ module = '.'.join(items[:-1])
+ obj = items[-1]
+ else:
+ return __import__(import_name)
+ return getattr(__import__(module, None, None, [obj]), obj)
+ except (ImportError, AttributeError):
+ if not silent:
+ raise
+
+
+def open_if_exists(filename, mode='rb'):
+ """Returns a file descriptor for the filename if that file exists,
+ otherwise `None`.
+ """
+ try:
+ return open(filename, mode)
+ except IOError as e:
+ if e.errno not in (errno.ENOENT, errno.EISDIR, errno.EINVAL):
+ raise
+
+
+def object_type_repr(obj):
+ """Returns the name of the object's type. For some recognized
+ singletons the name of the object is returned instead. (For
+ example for `None` and `Ellipsis`).
+ """
+ if obj is None:
+ return 'None'
+ elif obj is Ellipsis:
+ return 'Ellipsis'
+ # __builtin__ in 2.x, builtins in 3.x
+ if obj.__class__.__module__ in ('__builtin__', 'builtins'):
+ name = obj.__class__.__name__
+ else:
+ name = obj.__class__.__module__ + '.' + obj.__class__.__name__
+ return '%s object' % name
+
+
+def pformat(obj, verbose=False):
+ """Prettyprint an object. Either use the `pretty` library or the
+ builtin `pprint`.
+ """
+ try:
+ from pretty import pretty
+ return pretty(obj, verbose=verbose)
+ except ImportError:
+ from pprint import pformat
+ return pformat(obj)
+
+
+def urlize(text, trim_url_limit=None, nofollow=False, target=None):
+ """Converts any URLs in text into clickable links. Works on http://,
+ https:// and www. links. Links can have trailing punctuation (periods,
+ commas, close-parens) and leading punctuation (opening parens) and
+ it'll still do the right thing.
+
+ If trim_url_limit is not None, the URLs in link text will be limited
+ to trim_url_limit characters.
+
+ If nofollow is True, the URLs in link text will get a rel="nofollow"
+ attribute.
+
+ If target is not None, a target attribute will be added to the link.
+ """
+ trim_url = lambda x, limit=trim_url_limit: limit is not None \
+ and (x[:limit] + (len(x) >=limit and '...'
+ or '')) or x
+ words = _word_split_re.split(text_type(escape(text)))
+ nofollow_attr = nofollow and ' rel="nofollow"' or ''
+ if target is not None and isinstance(target, string_types):
+ target_attr = ' target="%s"' % target
+ else:
+ target_attr = ''
+ for i, word in enumerate(words):
+ match = _punctuation_re.match(word)
+ if match:
+ lead, middle, trail = match.groups()
+ if middle.startswith('www.') or (
+ '@' not in middle and
+ not middle.startswith('http://') and
+ not middle.startswith('https://') and
+ len(middle) > 0 and
+ middle[0] in _letters + _digits and (
+ middle.endswith('.org') or
+ middle.endswith('.net') or
+ middle.endswith('.com')
+ )):
+ middle = '<a href="http://%s"%s%s>%s</a>' % (middle,
+ nofollow_attr, target_attr, trim_url(middle))
+ if middle.startswith('http://') or \
+ middle.startswith('https://'):
+ middle = '<a href="%s"%s%s>%s</a>' % (middle,
+ nofollow_attr, target_attr, trim_url(middle))
+ if '@' in middle and not middle.startswith('www.') and \
+ not ':' in middle and _simple_email_re.match(middle):
+ middle = '<a href="mailto:%s">%s</a>' % (middle, middle)
+ if lead + middle + trail != word:
+ words[i] = lead + middle + trail
+ return u''.join(words)
+
+
+def generate_lorem_ipsum(n=5, html=True, min=20, max=100):
+ """Generate some lorem ipsum for the template."""
+ from jinja2.constants import LOREM_IPSUM_WORDS
+ from random import choice, randrange
+ words = LOREM_IPSUM_WORDS.split()
+ result = []
+
+ for _ in range(n):
+ next_capitalized = True
+ last_comma = last_fullstop = 0
+ word = None
+ last = None
+ p = []
+
+ # each paragraph contains out of 20 to 100 words.
+ for idx, _ in enumerate(range(randrange(min, max))):
+ while True:
+ word = choice(words)
+ if word != last:
+ last = word
+ break
+ if next_capitalized:
+ word = word.capitalize()
+ next_capitalized = False
+ # add commas
+ if idx - randrange(3, 8) > last_comma:
+ last_comma = idx
+ last_fullstop += 2
+ word += ','
+ # add end of sentences
+ if idx - randrange(10, 20) > last_fullstop:
+ last_comma = last_fullstop = idx
+ word += '.'
+ next_capitalized = True
+ p.append(word)
+
+ # ensure that the paragraph ends with a dot.
+ p = u' '.join(p)
+ if p.endswith(','):
+ p = p[:-1] + '.'
+ elif not p.endswith('.'):
+ p += '.'
+ result.append(p)
+
+ if not html:
+ return u'\n\n'.join(result)
+ return Markup(u'\n'.join(u'<p>%s</p>' % escape(x) for x in result))
+
+
+def unicode_urlencode(obj, charset='utf-8', for_qs=False):
+ """URL escapes a single bytestring or unicode string with the
+ given charset if applicable to URL safe quoting under all rules
+ that need to be considered under all supported Python versions.
+
+ If non strings are provided they are converted to their unicode
+ representation first.
+ """
+ if not isinstance(obj, string_types):
+ obj = text_type(obj)
+ if isinstance(obj, text_type):
+ obj = obj.encode(charset)
+ safe = not for_qs and b'/' or b''
+ rv = text_type(url_quote(obj, safe))
+ if for_qs:
+ rv = rv.replace('%20', '+')
+ return rv
+
+
+class LRUCache(object):
+ """A simple LRU Cache implementation."""
+
+ # this is fast for small capacities (something below 1000) but doesn't
+ # scale. But as long as it's only used as storage for templates this
+ # won't do any harm.
+
+ def __init__(self, capacity):
+ self.capacity = capacity
+ self._mapping = {}
+ self._queue = deque()
+ self._postinit()
+
+ def _postinit(self):
+ # alias all queue methods for faster lookup
+ self._popleft = self._queue.popleft
+ self._pop = self._queue.pop
+ self._remove = self._queue.remove
+ self._wlock = Lock()
+ self._append = self._queue.append
+
+ def __getstate__(self):
+ return {
+ 'capacity': self.capacity,
+ '_mapping': self._mapping,
+ '_queue': self._queue
+ }
+
+ def __setstate__(self, d):
+ self.__dict__.update(d)
+ self._postinit()
+
+ def __getnewargs__(self):
+ return (self.capacity,)
+
+ def copy(self):
+ """Return a shallow copy of the instance."""
+ rv = self.__class__(self.capacity)
+ rv._mapping.update(self._mapping)
+ rv._queue = deque(self._queue)
+ return rv
+
+ def get(self, key, default=None):
+ """Return an item from the cache dict or `default`"""
+ try:
+ return self[key]
+ except KeyError:
+ return default
+
+ def setdefault(self, key, default=None):
+ """Set `default` if the key is not in the cache otherwise
+ leave unchanged. Return the value of this key.
+ """
+ self._wlock.acquire()
+ try:
+ try:
+ return self[key]
+ except KeyError:
+ self[key] = default
+ return default
+ finally:
+ self._wlock.release()
+
+ def clear(self):
+ """Clear the cache."""
+ self._wlock.acquire()
+ try:
+ self._mapping.clear()
+ self._queue.clear()
+ finally:
+ self._wlock.release()
+
+ def __contains__(self, key):
+ """Check if a key exists in this cache."""
+ return key in self._mapping
+
+ def __len__(self):
+ """Return the current size of the cache."""
+ return len(self._mapping)
+
+ def __repr__(self):
+ return '<%s %r>' % (
+ self.__class__.__name__,
+ self._mapping
+ )
+
+ def __getitem__(self, key):
+ """Get an item from the cache. Moves the item up so that it has the
+ highest priority then.
+
+ Raise a `KeyError` if it does not exist.
+ """
+ self._wlock.acquire()
+ try:
+ rv = self._mapping[key]
+ if self._queue[-1] != key:
+ try:
+ self._remove(key)
+ except ValueError:
+ # if something removed the key from the container
+ # when we read, ignore the ValueError that we would
+ # get otherwise.
+ pass
+ self._append(key)
+ return rv
+ finally:
+ self._wlock.release()
+
+ def __setitem__(self, key, value):
+ """Sets the value for an item. Moves the item up so that it
+ has the highest priority then.
+ """
+ self._wlock.acquire()
+ try:
+ if key in self._mapping:
+ self._remove(key)
+ elif len(self._mapping) == self.capacity:
+ del self._mapping[self._popleft()]
+ self._append(key)
+ self._mapping[key] = value
+ finally:
+ self._wlock.release()
+
+ def __delitem__(self, key):
+ """Remove an item from the cache dict.
+ Raise a `KeyError` if it does not exist.
+ """
+ self._wlock.acquire()
+ try:
+ del self._mapping[key]
+ try:
+ self._remove(key)
+ except ValueError:
+ # __getitem__ is not locked, it might happen
+ pass
+ finally:
+ self._wlock.release()
+
+ def items(self):
+ """Return a list of items."""
+ result = [(key, self._mapping[key]) for key in list(self._queue)]
+ result.reverse()
+ return result
+
+ def iteritems(self):
+ """Iterate over all items."""
+ return iter(self.items())
+
+ def values(self):
+ """Return a list of all values."""
+ return [x[1] for x in self.items()]
+
+ def itervalue(self):
+ """Iterate over all values."""
+ return iter(self.values())
+
+ def keys(self):
+ """Return a list of all keys ordered by most recent usage."""
+ return list(self)
+
+ def iterkeys(self):
+ """Iterate over all keys in the cache dict, ordered by
+ the most recent usage.
+ """
+ return reversed(tuple(self._queue))
+
+ __iter__ = iterkeys
+
+ def __reversed__(self):
+ """Iterate over the values in the cache dict, oldest items
+ coming first.
+ """
+ return iter(tuple(self._queue))
+
+ __copy__ = copy
+
+
+# register the LRU cache as mutable mapping if possible
+try:
+ from collections import MutableMapping
+ MutableMapping.register(LRUCache)
+except ImportError:
+ pass
+
+
+@implements_iterator
+class Cycler(object):
+ """A cycle helper for templates."""
+
+ def __init__(self, *items):
+ if not items:
+ raise RuntimeError('at least one item has to be provided')
+ self.items = items
+ self.reset()
+
+ def reset(self):
+ """Resets the cycle."""
+ self.pos = 0
+
+ @property
+ def current(self):
+ """Returns the current item."""
+ return self.items[self.pos]
+
+ def __next__(self):
+ """Goes one item ahead and returns it."""
+ rv = self.current
+ self.pos = (self.pos + 1) % len(self.items)
+ return rv
+
+
+class Joiner(object):
+ """A joining helper for templates."""
+
+ def __init__(self, sep=u', '):
+ self.sep = sep
+ self.used = False
+
+ def __call__(self):
+ if not self.used:
+ self.used = True
+ return u''
+ return self.sep
+
+
+# Imported here because that's where it was in the past
+from markupsafe import Markup, escape, soft_unicode
diff --git a/deps/v8_inspector/deps/jinja2/jinja2/visitor.py b/deps/v8_inspector/deps/jinja2/jinja2/visitor.py
new file mode 100644
index 0000000000..413e7c309d
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/jinja2/visitor.py
@@ -0,0 +1,87 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.visitor
+ ~~~~~~~~~~~~~~
+
+ This module implements a visitor for the nodes.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD.
+"""
+from jinja2.nodes import Node
+
+
+class NodeVisitor(object):
+ """Walks the abstract syntax tree and call visitor functions for every
+ node found. The visitor functions may return values which will be
+ forwarded by the `visit` method.
+
+ Per default the visitor functions for the nodes are ``'visit_'`` +
+ class name of the node. So a `TryFinally` node visit function would
+ be `visit_TryFinally`. This behavior can be changed by overriding
+ the `get_visitor` function. If no visitor function exists for a node
+ (return value `None`) the `generic_visit` visitor is used instead.
+ """
+
+ def get_visitor(self, node):
+ """Return the visitor function for this node or `None` if no visitor
+ exists for this node. In that case the generic visit function is
+ used instead.
+ """
+ method = 'visit_' + node.__class__.__name__
+ return getattr(self, method, None)
+
+ def visit(self, node, *args, **kwargs):
+ """Visit a node."""
+ f = self.get_visitor(node)
+ if f is not None:
+ return f(node, *args, **kwargs)
+ return self.generic_visit(node, *args, **kwargs)
+
+ def generic_visit(self, node, *args, **kwargs):
+ """Called if no explicit visitor function exists for a node."""
+ for node in node.iter_child_nodes():
+ self.visit(node, *args, **kwargs)
+
+
+class NodeTransformer(NodeVisitor):
+ """Walks the abstract syntax tree and allows modifications of nodes.
+
+ The `NodeTransformer` will walk the AST and use the return value of the
+ visitor functions to replace or remove the old node. If the return
+ value of the visitor function is `None` the node will be removed
+ from the previous location otherwise it's replaced with the return
+ value. The return value may be the original node in which case no
+ replacement takes place.
+ """
+
+ def generic_visit(self, node, *args, **kwargs):
+ for field, old_value in node.iter_fields():
+ if isinstance(old_value, list):
+ new_values = []
+ for value in old_value:
+ if isinstance(value, Node):
+ value = self.visit(value, *args, **kwargs)
+ if value is None:
+ continue
+ elif not isinstance(value, Node):
+ new_values.extend(value)
+ continue
+ new_values.append(value)
+ old_value[:] = new_values
+ elif isinstance(old_value, Node):
+ new_node = self.visit(old_value, *args, **kwargs)
+ if new_node is None:
+ delattr(node, field)
+ else:
+ setattr(node, field, new_node)
+ return node
+
+ def visit_list(self, node, *args, **kwargs):
+ """As transformers may return lists in some places this method
+ can be used to enforce a list as return value.
+ """
+ rv = self.visit(node, *args, **kwargs)
+ if not isinstance(rv, list):
+ rv = [rv]
+ return rv
diff --git a/deps/v8_inspector/deps/jinja2/scripts/jinja2-debug.py b/deps/v8_inspector/deps/jinja2/scripts/jinja2-debug.py
new file mode 100755
index 0000000000..d052adc37e
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/scripts/jinja2-debug.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+ Jinja2 Debug Interface
+ ~~~~~~~~~~~~~~~~~~~~~~
+
+ Helper script for internal Jinja2 debugging. Requires Werkzeug.
+
+ :copyright: Copyright 2010 by Armin Ronacher.
+ :license: BSD.
+"""
+import sys
+import jinja2
+from werkzeug import script
+
+env = jinja2.Environment(extensions=['jinja2.ext.i18n', 'jinja2.ext.do',
+ 'jinja2.ext.loopcontrols',
+ 'jinja2.ext.with_',
+ 'jinja2.ext.autoescape'],
+ autoescape=True)
+
+def shell_init_func():
+ def _compile(x):
+ print(env.compile(x, raw=True))
+ result = {
+ 'e': env,
+ 'c': _compile,
+ 't': env.from_string,
+ 'p': env.parse
+ }
+ for key in jinja2.__all__:
+ result[key] = getattr(jinja2, key)
+ return result
+
+
+def action_compile():
+ print(env.compile(sys.stdin.read(), raw=True))
+
+action_shell = script.make_shell(shell_init_func)
+
+
+if __name__ == '__main__':
+ script.run()
diff --git a/deps/v8_inspector/deps/jinja2/scripts/make-release.py b/deps/v8_inspector/deps/jinja2/scripts/make-release.py
new file mode 100644
index 0000000000..6fd98fed54
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/scripts/make-release.py
@@ -0,0 +1,164 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+ make-release
+ ~~~~~~~~~~~~
+
+ Helper script that performs a release. Does pretty much everything
+ automatically for us.
+
+ :copyright: (c) 2011 by Armin Ronacher.
+ :license: BSD, see LICENSE for more details.
+"""
+import sys
+import os
+import re
+from datetime import datetime, date
+from subprocess import Popen, PIPE
+
+try:
+ import wheel
+except ImportError:
+ wheel = None
+
+_date_strip_re = re.compile(r'(?<=\d)(st|nd|rd|th)')
+
+
+def parse_changelog():
+ with open('CHANGES') as f:
+ lineiter = iter(f)
+ for line in lineiter:
+ match = re.search('^Version\s+(.*)', line.strip())
+ if match is None:
+ continue
+ length = len(match.group(1))
+ version = match.group(1).strip()
+ if lineiter.next().count('-') != len(match.group(0)):
+ continue
+ while 1:
+ change_info = lineiter.next().strip()
+ if change_info:
+ break
+
+ match = re.search(r'(?:codename (.*),\s*)?'
+ r'released on (\w+\s+\d+\w+\s+\d+)(?i)',
+ change_info)
+ if match is None:
+ continue
+
+ codename, datestr = match.groups()
+ return version, parse_date(datestr), codename
+
+
+def bump_version(version):
+ try:
+ parts = map(int, version.split('.'))
+ except ValueError:
+ fail('Current version is not numeric')
+ parts[-1] += 1
+ return '.'.join(map(str, parts))
+
+
+def parse_date(string):
+ string = _date_strip_re.sub('', string)
+ return datetime.strptime(string, '%B %d %Y')
+
+
+def set_filename_version(filename, version_number, pattern):
+ changed = []
+ def inject_version(match):
+ before, old, after = match.groups()
+ changed.append(True)
+ return before + version_number + after
+ with open(filename) as f:
+ contents = re.sub(r"^(\s*%s\s*=\s*')(.+?)(')(?sm)" % pattern,
+ inject_version, f.read())
+
+ if not changed:
+ fail('Could not find %s in %s', pattern, filename)
+
+ with open(filename, 'w') as f:
+ f.write(contents)
+
+
+def set_init_version(version):
+ info('Setting __init__.py version to %s', version)
+ set_filename_version('jinja2/__init__.py', version, '__version__')
+
+
+def set_setup_version(version):
+ info('Setting setup.py version to %s', version)
+ set_filename_version('setup.py', version, 'version')
+
+
+def build_and_upload():
+ cmd = [sys.executable, 'setup.py', 'release', 'sdist', 'bdist_wheel', 'upload']
+ if wheel is not None:
+ cmd.insert(4, 'bdist_wheel')
+ Popen(cmd).wait()
+
+
+def fail(message, *args):
+ print >> sys.stderr, 'Error:', message % args
+ sys.exit(1)
+
+
+def info(message, *args):
+ print >> sys.stderr, message % args
+
+
+def get_git_tags():
+ return set(Popen(['git', 'tag'], stdout=PIPE).communicate()[0].splitlines())
+
+
+def git_is_clean():
+ return Popen(['git', 'diff', '--quiet']).wait() == 0
+
+
+def make_git_commit(message, *args):
+ message = message % args
+ Popen(['git', 'commit', '-am', message]).wait()
+
+
+def make_git_tag(tag):
+ info('Tagging "%s"', tag)
+ Popen(['git', 'tag', tag]).wait()
+
+
+def main():
+ os.chdir(os.path.join(os.path.dirname(__file__), '..'))
+
+ rv = parse_changelog()
+ if rv is None:
+ fail('Could not parse changelog')
+
+ version, release_date, codename = rv
+ dev_version = bump_version(version) + '.dev'
+
+ info('Releasing %s (codename %s, release date %s)',
+ version, codename, release_date.strftime('%d/%m/%Y'))
+ tags = get_git_tags()
+
+ if version in tags:
+ fail('Version "%s" is already tagged', version)
+ if release_date.date() != date.today():
+ fail('Release date is not today (%s != %s)', release_date.date(), date.today())
+
+ if not git_is_clean():
+ fail('You have uncommitted changes in git')
+
+ if wheel is None:
+ print ('Warning: You need to install the wheel package '
+ 'to upload a wheel distribution.')
+
+ set_init_version(version)
+ set_setup_version(version)
+ make_git_commit('Bump version number to %s', version)
+ make_git_tag(version)
+ build_and_upload()
+ set_init_version(dev_version)
+ set_setup_version(dev_version)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/deps/v8_inspector/deps/jinja2/scripts/pylintrc b/deps/v8_inspector/deps/jinja2/scripts/pylintrc
new file mode 100644
index 0000000000..6ebf385bce
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/scripts/pylintrc
@@ -0,0 +1,301 @@
+# lint Python modules using external checkers.
+#
+# This is the main checker controling the other ones and the reports
+# generation. It is itself both a raw checker and an astng checker in order
+# to:
+# * handle message activation / deactivation at the module level
+# * handle some basic but necessary stats'data (number of classes, methods...)
+#
+[MASTER]
+
+# Specify a configuration file.
+#rcfile=
+
+# Profiled execution.
+profile=no
+
+# Add <file or directory> to the black list. It should be a base name, not a
+# path. You may set this option multiple times.
+ignore=.svn
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# Set the cache size for astng objects.
+cache-size=500
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+
+[MESSAGES CONTROL]
+
+# Enable only checker(s) with the given id(s). This option conflict with the
+# disable-checker option
+#enable-checker=
+
+# Enable all checker(s) except those with the given id(s). This option conflict
+# with the disable-checker option
+#disable-checker=
+
+# Enable all messages in the listed categories.
+#enable-msg-cat=
+
+# Disable all messages in the listed categories.
+#disable-msg-cat=
+
+# Enable the message(s) with the given id(s).
+#enable-msg=
+
+# Disable the message(s) with the given id(s).
+disable-msg=C0323,W0142,C0301,C0103,C0111,E0213,C0302,C0203,W0703,R0201
+
+
+[REPORTS]
+
+# set the output format. Available formats are text, parseable, colorized and
+# html
+output-format=colorized
+
+# Include message's id in output
+include-ids=yes
+
+# Put messages in a separate file for each module / package specified on the
+# command line instead of printing them on stdout. Reports (if any) will be
+# written in a file name "pylint_global.[txt|html]".
+files-output=no
+
+# Tells wether to display a full report or only the messages
+reports=yes
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note).You have access to the variables errors warning, statement which
+# respectivly contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (R0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Add a comment according to your evaluation note. This is used by the global
+# evaluation report (R0004).
+comment=no
+
+# Enable the report(s) with the given id(s).
+#enable-report=
+
+# Disable the report(s) with the given id(s).
+#disable-report=
+
+
+# checks for
+# * unused variables / imports
+# * undefined variables
+# * redefinition of variable from builtins or from an outer scope
+# * use of variable before assigment
+#
+[VARIABLES]
+
+# Tells wether we should check for unused import in __init__ files.
+init-import=no
+
+# A regular expression matching names used for dummy variables (i.e. not used).
+dummy-variables-rgx=_|dummy
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+
+# try to find bugs in the code using type inference
+#
+[TYPECHECK]
+
+# Tells wether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# When zope mode is activated, consider the acquired-members option to ignore
+# access to some undefined attributes.
+zope=no
+
+# List of members which are usually get through zope's acquisition mecanism and
+# so shouldn't trigger E0201 when accessed (need zope=yes to be considered).
+acquired-members=REQUEST,acl_users,aq_parent
+
+
+# checks for :
+# * doc strings
+# * modules / classes / functions / methods / arguments / variables name
+# * number of arguments, local variables, branchs, returns and statements in
+# functions, methods
+# * required module attributes
+# * dangerous default values as arguments
+# * redefinition of function / method / class
+# * uses of the global statement
+#
+[BASIC]
+
+# Required attributes for module, separated by a comma
+required-attributes=
+
+# Regular expression which should only match functions or classes name which do
+# not require a docstring
+no-docstring-rgx=__.*__
+
+# Regular expression which should only match correct module names
+module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression which should only match correct module level names
+const-rgx=(([A-Z_][A-Z1-9_]*)|(__.*__))$
+
+# Regular expression which should only match correct class names
+class-rgx=[A-Z_][a-zA-Z0-9]+$
+
+# Regular expression which should only match correct function names
+function-rgx=[a-z_][a-z0-9_]*$
+
+# Regular expression which should only match correct method names
+method-rgx=[a-z_][a-z0-9_]*$
+
+# Regular expression which should only match correct instance attribute names
+attr-rgx=[a-z_][a-z0-9_]*$
+
+# Regular expression which should only match correct argument names
+argument-rgx=[a-z_][a-z0-9_]*$
+
+# Regular expression which should only match correct variable names
+variable-rgx=[a-z_][a-z0-9_]*$
+
+# Regular expression which should only match correct list comprehension /
+# generator expression variable names
+inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,k,ex,Run,_
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=apply,input
+
+
+# checks for sign of poor/misdesign:
+# * number of methods, attributes, local variables...
+# * size, complexity of functions, methods
+#
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=12
+
+# Maximum number of locals for function / method body
+max-locals=30
+
+# Maximum number of return / yield for function / method body
+max-returns=12
+
+# Maximum number of branch for function / method body
+max-branchs=30
+
+# Maximum number of statements in function / method body
+max-statements=60
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=20
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=0
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+
+# checks for
+# * external modules dependencies
+# * relative / wildcard imports
+# * cyclic imports
+# * uses of deprecated modules
+#
+[IMPORTS]
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report R0402 must not be disabled)
+import-graph=
+
+# Create a graph of external dependencies in the given file (report R0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of internal dependencies in the given file (report R0402 must
+# not be disabled)
+int-import-graph=
+
+
+# checks for :
+# * methods without self as first argument
+# * overridden methods signature
+# * access only to existant members via self
+# * attributes not defined in the __init__ method
+# * supported interfaces implementation
+# * unreachable code
+#
+[CLASSES]
+
+# List of interface methods to ignore, separated by a comma. This is used for
+# instance to not check methods defines in Zope's Interface base class.
+ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__,setUp
+
+
+# checks for similarities and duplicated code. This computation may be
+# memory / CPU intensive, so you should disable it if you experiments some
+# problems.
+#
+[SIMILARITIES]
+
+# Minimum lines number of a similarity.
+min-similarity-lines=10
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+
+# checks for:
+# * warning notes in the code like FIXME, XXX
+# * PEP 263: source code with non ascii character but no encoding declaration
+#
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,XXX,TODO
+
+
+# checks for :
+# * unauthorized constructions
+# * strict indentation
+# * line length
+# * use of <> instead of !=
+#
+[FORMAT]
+
+# Maximum number of characters on a single line.
+max-line-length=90
+
+# Maximum number of lines in a module
+max-module-lines=1000
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string=' '
diff --git a/deps/v8_inspector/deps/jinja2/setup.cfg b/deps/v8_inspector/deps/jinja2/setup.cfg
new file mode 100644
index 0000000000..058cdfc1c6
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/setup.cfg
@@ -0,0 +1,8 @@
+[wheel]
+universal = 1
+
+[aliases]
+release = egg_info -RDb ''
+
+[pytest]
+norecursedirs = .* *.egg *.egg-info env* artwork docs examples
diff --git a/deps/v8_inspector/deps/jinja2/setup.py b/deps/v8_inspector/deps/jinja2/setup.py
new file mode 100644
index 0000000000..507fd07353
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/setup.py
@@ -0,0 +1,77 @@
+# -*- coding: utf-8 -*-
+"""
+Jinja2
+~~~~~~
+
+Jinja2 is a template engine written in pure Python. It provides a
+`Django`_ inspired non-XML syntax but supports inline expressions and
+an optional `sandboxed`_ environment.
+
+Nutshell
+--------
+
+Here a small example of a Jinja template::
+
+ {% extends 'base.html' %}
+ {% block title %}Memberlist{% endblock %}
+ {% block content %}
+ <ul>
+ {% for user in users %}
+ <li><a href="{{ user.url }}">{{ user.username }}</a></li>
+ {% endfor %}
+ </ul>
+ {% endblock %}
+
+Philosophy
+----------
+
+Application logic is for the controller but don't try to make the life
+for the template designer too hard by giving him too few functionality.
+
+For more informations visit the new `Jinja2 webpage`_ and `documentation`_.
+
+.. _sandboxed: http://en.wikipedia.org/wiki/Sandbox_(computer_security)
+.. _Django: http://www.djangoproject.com/
+.. _Jinja2 webpage: http://jinja.pocoo.org/
+.. _documentation: http://jinja.pocoo.org/2/documentation/
+"""
+from setuptools import setup
+
+
+setup(
+ name='Jinja2',
+ version='2.9.dev',
+ url='http://jinja.pocoo.org/',
+ license='BSD',
+ author='Armin Ronacher',
+ author_email='armin.ronacher@active-4.com',
+ description='A small but fast and easy to use stand-alone template '
+ 'engine written in pure python.',
+ long_description=__doc__,
+ # jinja is egg safe. But we hate eggs
+ zip_safe=False,
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Web Environment',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: BSD License',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 2',
+ 'Programming Language :: Python :: 2.6',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.3',
+ 'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
+ 'Topic :: Software Development :: Libraries :: Python Modules',
+ 'Topic :: Text Processing :: Markup :: HTML'
+ ],
+ packages=['jinja2'],
+ install_requires=['MarkupSafe'],
+ extras_require={'i18n': ['Babel>=0.8']},
+ include_package_data=True,
+ entry_points="""
+ [babel.extractors]
+ jinja2 = jinja2.ext:babel_extract[i18n]
+ """
+)
diff --git a/deps/v8_inspector/deps/jinja2/tests/conftest.py b/deps/v8_inspector/deps/jinja2/tests/conftest.py
new file mode 100644
index 0000000000..b5582323d7
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/tests/conftest.py
@@ -0,0 +1,74 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.conftest
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Configuration and Fixtures for the tests
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import pytest
+import os
+import re
+import sys
+
+from traceback import format_exception
+from jinja2 import loaders
+from jinja2._compat import PY2
+from jinja2 import Environment
+
+
+@pytest.fixture
+def env():
+ '''returns a new environment.
+ '''
+ return Environment()
+
+
+@pytest.fixture
+def dict_loader():
+ '''returns DictLoader
+ '''
+ return loaders.DictLoader({
+ 'justdict.html': 'FOO'
+ })
+
+
+@pytest.fixture
+def package_loader():
+ '''returns PackageLoader initialized from templates
+ '''
+ return loaders.PackageLoader('res', 'templates')
+
+
+@pytest.fixture
+def filesystem_loader():
+ '''returns FileSystemLoader initialized to res/templates directory
+ '''
+ here = os.path.dirname(os.path.abspath(__file__))
+ return loaders.FileSystemLoader(here + '/res/templates')
+
+
+@pytest.fixture
+def function_loader():
+ '''returns a FunctionLoader
+ '''
+ return loaders.FunctionLoader({'justfunction.html': 'FOO'}.get)
+
+
+@pytest.fixture
+def choice_loader(dict_loader, package_loader):
+ '''returns a ChoiceLoader
+ '''
+ return loaders.ChoiceLoader([dict_loader, package_loader])
+
+
+@pytest.fixture
+def prefix_loader(filesystem_loader, dict_loader):
+ '''returns a PrefixLoader
+ '''
+ return loaders.PrefixLoader({
+ 'a': filesystem_loader,
+ 'b': dict_loader
+ })
diff --git a/deps/v8_inspector/deps/jinja2/tests/res/__init__.py b/deps/v8_inspector/deps/jinja2/tests/res/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/tests/res/__init__.py
diff --git a/deps/v8_inspector/deps/jinja2/tests/res/templates/broken.html b/deps/v8_inspector/deps/jinja2/tests/res/templates/broken.html
new file mode 100644
index 0000000000..77669fae57
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/tests/res/templates/broken.html
@@ -0,0 +1,3 @@
+Before
+{{ fail() }}
+After
diff --git a/deps/v8_inspector/deps/jinja2/tests/res/templates/foo/test.html b/deps/v8_inspector/deps/jinja2/tests/res/templates/foo/test.html
new file mode 100644
index 0000000000..b7d6715e2d
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/tests/res/templates/foo/test.html
@@ -0,0 +1 @@
+FOO
diff --git a/deps/v8_inspector/deps/jinja2/tests/res/templates/syntaxerror.html b/deps/v8_inspector/deps/jinja2/tests/res/templates/syntaxerror.html
new file mode 100644
index 0000000000..f21b817939
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/tests/res/templates/syntaxerror.html
@@ -0,0 +1,4 @@
+Foo
+{% for item in broken %}
+ ...
+{% endif %}
diff --git a/deps/v8_inspector/deps/jinja2/tests/res/templates/test.html b/deps/v8_inspector/deps/jinja2/tests/res/templates/test.html
new file mode 100644
index 0000000000..ba578e48b1
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/tests/res/templates/test.html
@@ -0,0 +1 @@
+BAR
diff --git a/deps/v8_inspector/deps/jinja2/tests/test_api.py b/deps/v8_inspector/deps/jinja2/tests/test_api.py
new file mode 100644
index 0000000000..99d8dc1e13
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/tests/test_api.py
@@ -0,0 +1,327 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.api
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Tests the public API and related stuff.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import os
+import tempfile
+import shutil
+
+import pytest
+from jinja2 import Environment, Undefined, DebugUndefined, \
+ StrictUndefined, UndefinedError, meta, \
+ is_undefined, Template, DictLoader, make_logging_undefined
+from jinja2.compiler import CodeGenerator
+from jinja2.runtime import Context
+from jinja2.utils import Cycler
+
+
+@pytest.mark.api
+@pytest.mark.extended
+class TestExtendedAPI():
+
+ def test_item_and_attribute(self, env):
+ from jinja2.sandbox import SandboxedEnvironment
+
+ for env in Environment(), SandboxedEnvironment():
+ # the |list is necessary for python3
+ tmpl = env.from_string('{{ foo.items()|list }}')
+ assert tmpl.render(foo={'items': 42}) == "[('items', 42)]"
+ tmpl = env.from_string('{{ foo|attr("items")()|list }}')
+ assert tmpl.render(foo={'items': 42}) == "[('items', 42)]"
+ tmpl = env.from_string('{{ foo["items"] }}')
+ assert tmpl.render(foo={'items': 42}) == '42'
+
+ def test_finalizer(self, env):
+ def finalize_none_empty(value):
+ if value is None:
+ value = u''
+ return value
+ env = Environment(finalize=finalize_none_empty)
+ tmpl = env.from_string('{% for item in seq %}|{{ item }}{% endfor %}')
+ assert tmpl.render(seq=(None, 1, "foo")) == '||1|foo'
+ tmpl = env.from_string('<{{ none }}>')
+ assert tmpl.render() == '<>'
+
+ def test_cycler(self, env):
+ items = 1, 2, 3
+ c = Cycler(*items)
+ for item in items + items:
+ assert c.current == item
+ assert next(c) == item
+ next(c)
+ assert c.current == 2
+ c.reset()
+ assert c.current == 1
+
+ def test_expressions(self, env):
+ expr = env.compile_expression("foo")
+ assert expr() is None
+ assert expr(foo=42) == 42
+ expr2 = env.compile_expression("foo", undefined_to_none=False)
+ assert is_undefined(expr2())
+
+ expr = env.compile_expression("42 + foo")
+ assert expr(foo=42) == 84
+
+ def test_template_passthrough(self, env):
+ t = Template('Content')
+ assert env.get_template(t) is t
+ assert env.select_template([t]) is t
+ assert env.get_or_select_template([t]) is t
+ assert env.get_or_select_template(t) is t
+
+ def test_autoescape_autoselect(self, env):
+ def select_autoescape(name):
+ if name is None or '.' not in name:
+ return False
+ return name.endswith('.html')
+ env = Environment(autoescape=select_autoescape,
+ loader=DictLoader({
+ 'test.txt': '{{ foo }}',
+ 'test.html': '{{ foo }}'
+ }))
+ t = env.get_template('test.txt')
+ assert t.render(foo='<foo>') == '<foo>'
+ t = env.get_template('test.html')
+ assert t.render(foo='<foo>') == '&lt;foo&gt;'
+ t = env.from_string('{{ foo }}')
+ assert t.render(foo='<foo>') == '<foo>'
+
+
+@pytest.mark.api
+@pytest.mark.meta
+class TestMeta():
+
+ def test_find_undeclared_variables(self, env):
+ ast = env.parse('{% set foo = 42 %}{{ bar + foo }}')
+ x = meta.find_undeclared_variables(ast)
+ assert x == set(['bar'])
+
+ ast = env.parse('{% set foo = 42 %}{{ bar + foo }}'
+ '{% macro meh(x) %}{{ x }}{% endmacro %}'
+ '{% for item in seq %}{{ muh(item) + meh(seq) }}'
+ '{% endfor %}')
+ x = meta.find_undeclared_variables(ast)
+ assert x == set(['bar', 'seq', 'muh'])
+
+ def test_find_refererenced_templates(self, env):
+ ast = env.parse('{% extends "layout.html" %}{% include helper %}')
+ i = meta.find_referenced_templates(ast)
+ assert next(i) == 'layout.html'
+ assert next(i) is None
+ assert list(i) == []
+
+ ast = env.parse('{% extends "layout.html" %}'
+ '{% from "test.html" import a, b as c %}'
+ '{% import "meh.html" as meh %}'
+ '{% include "muh.html" %}')
+ i = meta.find_referenced_templates(ast)
+ assert list(i) == ['layout.html', 'test.html', 'meh.html', 'muh.html']
+
+ def test_find_included_templates(self, env):
+ ast = env.parse('{% include ["foo.html", "bar.html"] %}')
+ i = meta.find_referenced_templates(ast)
+ assert list(i) == ['foo.html', 'bar.html']
+
+ ast = env.parse('{% include ("foo.html", "bar.html") %}')
+ i = meta.find_referenced_templates(ast)
+ assert list(i) == ['foo.html', 'bar.html']
+
+ ast = env.parse('{% include ["foo.html", "bar.html", foo] %}')
+ i = meta.find_referenced_templates(ast)
+ assert list(i) == ['foo.html', 'bar.html', None]
+
+ ast = env.parse('{% include ("foo.html", "bar.html", foo) %}')
+ i = meta.find_referenced_templates(ast)
+ assert list(i) == ['foo.html', 'bar.html', None]
+
+
+@pytest.mark.api
+@pytest.mark.streaming
+class TestStreaming():
+
+ def test_basic_streaming(self, env):
+ tmpl = env.from_string("<ul>{% for item in seq %}<li>{{ loop.index "
+ "}} - {{ item }}</li>{%- endfor %}</ul>")
+ stream = tmpl.stream(seq=list(range(4)))
+ assert next(stream) == '<ul>'
+ assert next(stream) == '<li>1 - 0</li>'
+ assert next(stream) == '<li>2 - 1</li>'
+ assert next(stream) == '<li>3 - 2</li>'
+ assert next(stream) == '<li>4 - 3</li>'
+ assert next(stream) == '</ul>'
+
+ def test_buffered_streaming(self, env):
+ tmpl = env.from_string("<ul>{% for item in seq %}<li>{{ loop.index "
+ "}} - {{ item }}</li>{%- endfor %}</ul>")
+ stream = tmpl.stream(seq=list(range(4)))
+ stream.enable_buffering(size=3)
+ assert next(stream) == u'<ul><li>1 - 0</li><li>2 - 1</li>'
+ assert next(stream) == u'<li>3 - 2</li><li>4 - 3</li></ul>'
+
+ def test_streaming_behavior(self, env):
+ tmpl = env.from_string("")
+ stream = tmpl.stream()
+ assert not stream.buffered
+ stream.enable_buffering(20)
+ assert stream.buffered
+ stream.disable_buffering()
+ assert not stream.buffered
+
+ def test_dump_stream(self, env):
+ tmp = tempfile.mkdtemp()
+ try:
+ tmpl = env.from_string(u"\u2713")
+ stream = tmpl.stream()
+ stream.dump(os.path.join(tmp, 'dump.txt'), 'utf-8')
+ with open(os.path.join(tmp, 'dump.txt'), 'rb') as f:
+ assert f.read() == b'\xe2\x9c\x93'
+ finally:
+ shutil.rmtree(tmp)
+
+
+@pytest.mark.api
+@pytest.mark.undefined
+class TestUndefined():
+
+ def test_stopiteration_is_undefined(self):
+ def test():
+ raise StopIteration()
+ t = Template('A{{ test() }}B')
+ assert t.render(test=test) == 'AB'
+ t = Template('A{{ test().missingattribute }}B')
+ pytest.raises(UndefinedError, t.render, test=test)
+
+ def test_undefined_and_special_attributes(self):
+ try:
+ Undefined('Foo').__dict__
+ except AttributeError:
+ pass
+ else:
+ assert False, "Expected actual attribute error"
+
+ def test_logging_undefined(self):
+ _messages = []
+
+ class DebugLogger(object):
+ def warning(self, msg, *args):
+ _messages.append('W:' + msg % args)
+
+ def error(self, msg, *args):
+ _messages.append('E:' + msg % args)
+
+ logging_undefined = make_logging_undefined(DebugLogger())
+ env = Environment(undefined=logging_undefined)
+ assert env.from_string('{{ missing }}').render() == u''
+ pytest.raises(UndefinedError,
+ env.from_string('{{ missing.attribute }}').render)
+ assert env.from_string('{{ missing|list }}').render() == '[]'
+ assert env.from_string('{{ missing is not defined }}').render() \
+ == 'True'
+ assert env.from_string('{{ foo.missing }}').render(foo=42) == ''
+ assert env.from_string('{{ not missing }}').render() == 'True'
+ assert _messages == [
+ 'W:Template variable warning: missing is undefined',
+ "E:Template variable error: 'missing' is undefined",
+ 'W:Template variable warning: missing is undefined',
+ 'W:Template variable warning: int object has no attribute missing',
+ 'W:Template variable warning: missing is undefined',
+ ]
+
+ def test_default_undefined(self):
+ env = Environment(undefined=Undefined)
+ assert env.from_string('{{ missing }}').render() == u''
+ pytest.raises(UndefinedError,
+ env.from_string('{{ missing.attribute }}').render)
+ assert env.from_string('{{ missing|list }}').render() == '[]'
+ assert env.from_string('{{ missing is not defined }}').render() \
+ == 'True'
+ assert env.from_string('{{ foo.missing }}').render(foo=42) == ''
+ assert env.from_string('{{ not missing }}').render() == 'True'
+
+ def test_debug_undefined(self):
+ env = Environment(undefined=DebugUndefined)
+ assert env.from_string('{{ missing }}').render() == '{{ missing }}'
+ pytest.raises(UndefinedError,
+ env.from_string('{{ missing.attribute }}').render)
+ assert env.from_string('{{ missing|list }}').render() == '[]'
+ assert env.from_string('{{ missing is not defined }}').render() \
+ == 'True'
+ assert env.from_string('{{ foo.missing }}').render(foo=42) \
+ == u"{{ no such element: int object['missing'] }}"
+ assert env.from_string('{{ not missing }}').render() == 'True'
+
+ def test_strict_undefined(self):
+ env = Environment(undefined=StrictUndefined)
+ pytest.raises(UndefinedError, env.from_string('{{ missing }}').render)
+ pytest.raises(UndefinedError,
+ env.from_string('{{ missing.attribute }}').render)
+ pytest.raises(UndefinedError,
+ env.from_string('{{ missing|list }}').render)
+ assert env.from_string('{{ missing is not defined }}').render() \
+ == 'True'
+ pytest.raises(UndefinedError,
+ env.from_string('{{ foo.missing }}').render, foo=42)
+ pytest.raises(UndefinedError,
+ env.from_string('{{ not missing }}').render)
+ assert env.from_string('{{ missing|default("default", true) }}')\
+ .render() == 'default'
+
+ def test_indexing_gives_undefined(self):
+ t = Template("{{ var[42].foo }}")
+ pytest.raises(UndefinedError, t.render, var=0)
+
+ def test_none_gives_proper_error(self):
+ try:
+ Environment().getattr(None, 'split')()
+ except UndefinedError as e:
+ assert e.message == "'None' has no attribute 'split'"
+ else:
+ assert False, 'expected exception'
+
+ def test_object_repr(self):
+ try:
+ Undefined(obj=42, name='upper')()
+ except UndefinedError as e:
+ assert e.message == "'int object' has no attribute 'upper'"
+ else:
+ assert False, 'expected exception'
+
+
+@pytest.mark.api
+@pytest.mark.lowlevel
+class TestLowLevel():
+
+ def test_custom_code_generator(self):
+ class CustomCodeGenerator(CodeGenerator):
+ def visit_Const(self, node, frame=None):
+ # This method is pure nonsense, but works fine for testing...
+ if node.value == 'foo':
+ self.write(repr('bar'))
+ else:
+ super(CustomCodeGenerator, self).visit_Const(node, frame)
+
+ class CustomEnvironment(Environment):
+ code_generator_class = CustomCodeGenerator
+
+ env = CustomEnvironment()
+ tmpl = env.from_string('{% set foo = "foo" %}{{ foo }}')
+ assert tmpl.render() == 'bar'
+
+ def test_custom_context(self):
+ class CustomContext(Context):
+ def resolve(self, key):
+ return 'resolve-' + key
+
+ class CustomEnvironment(Environment):
+ context_class = CustomContext
+
+ env = CustomEnvironment()
+ tmpl = env.from_string('{{ foo }}')
+ assert tmpl.render() == 'resolve-foo'
diff --git a/deps/v8_inspector/deps/jinja2/tests/test_bytecode_cache.py b/deps/v8_inspector/deps/jinja2/tests/test_bytecode_cache.py
new file mode 100644
index 0000000000..2ffe4c6037
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/tests/test_bytecode_cache.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.bytecode_cache
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Test bytecode caching
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import pytest
+from jinja2 import Environment
+from jinja2.bccache import FileSystemBytecodeCache
+from jinja2.exceptions import TemplateNotFound
+
+
+@pytest.fixture
+def env(package_loader):
+ bytecode_cache = FileSystemBytecodeCache()
+ return Environment(
+ loader=package_loader,
+ bytecode_cache=bytecode_cache,
+ )
+
+
+@pytest.mark.byte_code_cache
+class TestByteCodeCache():
+
+ def test_simple(self, env):
+ tmpl = env.get_template('test.html')
+ assert tmpl.render().strip() == 'BAR'
+ pytest.raises(TemplateNotFound, env.get_template, 'missing.html')
diff --git a/deps/v8_inspector/deps/jinja2/tests/test_core_tags.py b/deps/v8_inspector/deps/jinja2/tests/test_core_tags.py
new file mode 100644
index 0000000000..2ea7757e48
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/tests/test_core_tags.py
@@ -0,0 +1,337 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.core_tags
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Test the core tags like for and if.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import pytest
+from jinja2 import Environment, TemplateSyntaxError, UndefinedError, \
+ DictLoader
+
+
+@pytest.fixture
+def env_trim():
+ return Environment(trim_blocks=True)
+
+
+@pytest.mark.core_tags
+@pytest.mark.for_loop
+class TestForLoop():
+
+ def test_simple(self, env):
+ tmpl = env.from_string('{% for item in seq %}{{ item }}{% endfor %}')
+ assert tmpl.render(seq=list(range(10))) == '0123456789'
+
+ def test_else(self, env):
+ tmpl = env.from_string(
+ '{% for item in seq %}XXX{% else %}...{% endfor %}')
+ assert tmpl.render() == '...'
+
+ def test_empty_blocks(self, env):
+ tmpl = env.from_string('<{% for item in seq %}{% else %}{% endfor %}>')
+ assert tmpl.render() == '<>'
+
+ def test_context_vars(self, env):
+ slist = [42, 24]
+ for seq in [slist, iter(slist), reversed(slist), (_ for _ in slist)]:
+ tmpl = env.from_string('''{% for item in seq -%}
+ {{ loop.index }}|{{ loop.index0 }}|{{ loop.revindex }}|{{
+ loop.revindex0 }}|{{ loop.first }}|{{ loop.last }}|{{
+ loop.length }}###{% endfor %}''')
+ one, two, _ = tmpl.render(seq=seq).split('###')
+ (one_index, one_index0, one_revindex, one_revindex0, one_first,
+ one_last, one_length) = one.split('|')
+ (two_index, two_index0, two_revindex, two_revindex0, two_first,
+ two_last, two_length) = two.split('|')
+
+ assert int(one_index) == 1 and int(two_index) == 2
+ assert int(one_index0) == 0 and int(two_index0) == 1
+ assert int(one_revindex) == 2 and int(two_revindex) == 1
+ assert int(one_revindex0) == 1 and int(two_revindex0) == 0
+ assert one_first == 'True' and two_first == 'False'
+ assert one_last == 'False' and two_last == 'True'
+ assert one_length == two_length == '2'
+
+ def test_cycling(self, env):
+ tmpl = env.from_string('''{% for item in seq %}{{
+ loop.cycle('<1>', '<2>') }}{% endfor %}{%
+ for item in seq %}{{ loop.cycle(*through) }}{% endfor %}''')
+ output = tmpl.render(seq=list(range(4)), through=('<1>', '<2>'))
+ assert output == '<1><2>' * 4
+
+ def test_scope(self, env):
+ tmpl = env.from_string('{% for item in seq %}{% endfor %}{{ item }}')
+ output = tmpl.render(seq=list(range(10)))
+ assert not output
+
+ def test_varlen(self, env):
+ def inner():
+ for item in range(5):
+ yield item
+ tmpl = env.from_string('{% for item in iter %}{{ item }}{% endfor %}')
+ output = tmpl.render(iter=inner())
+ assert output == '01234'
+
+ def test_noniter(self, env):
+ tmpl = env.from_string('{% for item in none %}...{% endfor %}')
+ pytest.raises(TypeError, tmpl.render)
+
+ def test_recursive(self, env):
+ tmpl = env.from_string('''{% for item in seq recursive -%}
+ [{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
+ {%- endfor %}''')
+ assert tmpl.render(seq=[
+ dict(a=1, b=[dict(a=1), dict(a=2)]),
+ dict(a=2, b=[dict(a=1), dict(a=2)]),
+ dict(a=3, b=[dict(a='a')])
+ ]) == '[1<[1][2]>][2<[1][2]>][3<[a]>]'
+
+ def test_recursive_depth0(self, env):
+ tmpl = env.from_string('''{% for item in seq recursive -%}
+ [{{ loop.depth0 }}:{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
+ {%- endfor %}''')
+ assert tmpl.render(seq=[
+ dict(a=1, b=[dict(a=1), dict(a=2)]),
+ dict(a=2, b=[dict(a=1), dict(a=2)]),
+ dict(a=3, b=[dict(a='a')])
+ ]) == '[0:1<[1:1][1:2]>][0:2<[1:1][1:2]>][0:3<[1:a]>]'
+
+ def test_recursive_depth(self, env):
+ tmpl = env.from_string('''{% for item in seq recursive -%}
+ [{{ loop.depth }}:{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
+ {%- endfor %}''')
+ assert tmpl.render(seq=[
+ dict(a=1, b=[dict(a=1), dict(a=2)]),
+ dict(a=2, b=[dict(a=1), dict(a=2)]),
+ dict(a=3, b=[dict(a='a')])
+ ]) == '[1:1<[2:1][2:2]>][1:2<[2:1][2:2]>][1:3<[2:a]>]'
+
+ def test_looploop(self, env):
+ tmpl = env.from_string('''{% for row in table %}
+ {%- set rowloop = loop -%}
+ {% for cell in row -%}
+ [{{ rowloop.index }}|{{ loop.index }}]
+ {%- endfor %}
+ {%- endfor %}''')
+ assert tmpl.render(table=['ab', 'cd']) == '[1|1][1|2][2|1][2|2]'
+
+ def test_reversed_bug(self, env):
+ tmpl = env.from_string('{% for i in items %}{{ i }}'
+ '{% if not loop.last %}'
+ ',{% endif %}{% endfor %}')
+ assert tmpl.render(items=reversed([3, 2, 1])) == '1,2,3'
+
+ def test_loop_errors(self, env):
+ tmpl = env.from_string('''{% for item in [1] if loop.index
+ == 0 %}...{% endfor %}''')
+ pytest.raises(UndefinedError, tmpl.render)
+ tmpl = env.from_string('''{% for item in [] %}...{% else
+ %}{{ loop }}{% endfor %}''')
+ assert tmpl.render() == ''
+
+ def test_loop_filter(self, env):
+ tmpl = env.from_string('{% for item in range(10) if item '
+ 'is even %}[{{ item }}]{% endfor %}')
+ assert tmpl.render() == '[0][2][4][6][8]'
+ tmpl = env.from_string('''
+ {%- for item in range(10) if item is even %}[{{
+ loop.index }}:{{ item }}]{% endfor %}''')
+ assert tmpl.render() == '[1:0][2:2][3:4][4:6][5:8]'
+
+ def test_loop_unassignable(self, env):
+ pytest.raises(TemplateSyntaxError, env.from_string,
+ '{% for loop in seq %}...{% endfor %}')
+
+ def test_scoped_special_var(self, env):
+ t = env.from_string(
+ '{% for s in seq %}[{{ loop.first }}{% for c in s %}'
+ '|{{ loop.first }}{% endfor %}]{% endfor %}')
+ assert t.render(seq=('ab', 'cd')) \
+ == '[True|True|False][False|True|False]'
+
+ def test_scoped_loop_var(self, env):
+ t = env.from_string('{% for x in seq %}{{ loop.first }}'
+ '{% for y in seq %}{% endfor %}{% endfor %}')
+ assert t.render(seq='ab') == 'TrueFalse'
+ t = env.from_string('{% for x in seq %}{% for y in seq %}'
+ '{{ loop.first }}{% endfor %}{% endfor %}')
+ assert t.render(seq='ab') == 'TrueFalseTrueFalse'
+
+ def test_recursive_empty_loop_iter(self, env):
+ t = env.from_string('''
+ {%- for item in foo recursive -%}{%- endfor -%}
+ ''')
+ assert t.render(dict(foo=[])) == ''
+
+ def test_call_in_loop(self, env):
+ t = env.from_string('''
+ {%- macro do_something() -%}
+ [{{ caller() }}]
+ {%- endmacro %}
+
+ {%- for i in [1, 2, 3] %}
+ {%- call do_something() -%}
+ {{ i }}
+ {%- endcall %}
+ {%- endfor -%}
+ ''')
+ assert t.render() == '[1][2][3]'
+
+ def test_scoping_bug(self, env):
+ t = env.from_string('''
+ {%- for item in foo %}...{{ item }}...{% endfor %}
+ {%- macro item(a) %}...{{ a }}...{% endmacro %}
+ {{- item(2) -}}
+ ''')
+ assert t.render(foo=(1,)) == '...1......2...'
+
+ def test_unpacking(self, env):
+ tmpl = env.from_string('{% for a, b, c in [[1, 2, 3]] %}'
+ '{{ a }}|{{ b }}|{{ c }}{% endfor %}')
+ assert tmpl.render() == '1|2|3'
+
+
+@pytest.mark.core_tags
+@pytest.mark.if_condition
+class TestIfCondition():
+
+ def test_simple(self, env):
+ tmpl = env.from_string('''{% if true %}...{% endif %}''')
+ assert tmpl.render() == '...'
+
+ def test_elif(self, env):
+ tmpl = env.from_string('''{% if false %}XXX{% elif true
+ %}...{% else %}XXX{% endif %}''')
+ assert tmpl.render() == '...'
+
+ def test_else(self, env):
+ tmpl = env.from_string('{% if false %}XXX{% else %}...{% endif %}')
+ assert tmpl.render() == '...'
+
+ def test_empty(self, env):
+ tmpl = env.from_string('[{% if true %}{% else %}{% endif %}]')
+ assert tmpl.render() == '[]'
+
+ def test_complete(self, env):
+ tmpl = env.from_string('{% if a %}A{% elif b %}B{% elif c == d %}'
+ 'C{% else %}D{% endif %}')
+ assert tmpl.render(a=0, b=False, c=42, d=42.0) == 'C'
+
+ def test_no_scope(self, env):
+ tmpl = env.from_string(
+ '{% if a %}{% set foo = 1 %}{% endif %}{{ foo }}')
+ assert tmpl.render(a=True) == '1'
+ tmpl = env.from_string(
+ '{% if true %}{% set foo = 1 %}{% endif %}{{ foo }}')
+ assert tmpl.render() == '1'
+
+
+@pytest.mark.core_tags
+@pytest.mark.macros
+class TestMacros():
+ def test_simple(self, env_trim):
+ tmpl = env_trim.from_string('''\
+{% macro say_hello(name) %}Hello {{ name }}!{% endmacro %}
+{{ say_hello('Peter') }}''')
+ assert tmpl.render() == 'Hello Peter!'
+
+ def test_scoping(self, env_trim):
+ tmpl = env_trim.from_string('''\
+{% macro level1(data1) %}
+{% macro level2(data2) %}{{ data1 }}|{{ data2 }}{% endmacro %}
+{{ level2('bar') }}{% endmacro %}
+{{ level1('foo') }}''')
+ assert tmpl.render() == 'foo|bar'
+
+ def test_arguments(self, env_trim):
+ tmpl = env_trim.from_string('''\
+{% macro m(a, b, c='c', d='d') %}{{ a }}|{{ b }}|{{ c }}|{{ d }}{% endmacro %}
+{{ m() }}|{{ m('a') }}|{{ m('a', 'b') }}|{{ m(1, 2, 3) }}''')
+ assert tmpl.render() == '||c|d|a||c|d|a|b|c|d|1|2|3|d'
+
+ def test_arguments_defaults_nonsense(self, env_trim):
+ pytest.raises(TemplateSyntaxError, env_trim.from_string, '''\
+{% macro m(a, b=1, c) %}a={{ a }}, b={{ b }}, c={{ c }}{% endmacro %}''')
+
+ def test_caller_defaults_nonsense(self, env_trim):
+ pytest.raises(TemplateSyntaxError, env_trim.from_string, '''\
+{% macro a() %}{{ caller() }}{% endmacro %}
+{% call(x, y=1, z) a() %}{% endcall %}''')
+
+ def test_varargs(self, env_trim):
+ tmpl = env_trim.from_string('''\
+{% macro test() %}{{ varargs|join('|') }}{% endmacro %}\
+{{ test(1, 2, 3) }}''')
+ assert tmpl.render() == '1|2|3'
+
+ def test_simple_call(self, env_trim):
+ tmpl = env_trim.from_string('''\
+{% macro test() %}[[{{ caller() }}]]{% endmacro %}\
+{% call test() %}data{% endcall %}''')
+ assert tmpl.render() == '[[data]]'
+
+ def test_complex_call(self, env_trim):
+ tmpl = env_trim.from_string('''\
+{% macro test() %}[[{{ caller('data') }}]]{% endmacro %}\
+{% call(data) test() %}{{ data }}{% endcall %}''')
+ assert tmpl.render() == '[[data]]'
+
+ def test_caller_undefined(self, env_trim):
+ tmpl = env_trim.from_string('''\
+{% set caller = 42 %}\
+{% macro test() %}{{ caller is not defined }}{% endmacro %}\
+{{ test() }}''')
+ assert tmpl.render() == 'True'
+
+ def test_include(self, env_trim):
+ env_trim = Environment(
+ loader=DictLoader({
+ 'include': '{% macro test(foo) %}[{{ foo }}]{% endmacro %}'
+ })
+ )
+ tmpl = env_trim.from_string(
+ '{% from "include" import test %}{{ test("foo") }}')
+ assert tmpl.render() == '[foo]'
+
+ def test_macro_api(self, env_trim):
+ tmpl = env_trim.from_string(
+ '{% macro foo(a, b) %}{% endmacro %}'
+ '{% macro bar() %}{{ varargs }}{{ kwargs }}{% endmacro %}'
+ '{% macro baz() %}{{ caller() }}{% endmacro %}')
+ assert tmpl.module.foo.arguments == ('a', 'b')
+ assert tmpl.module.foo.defaults == ()
+ assert tmpl.module.foo.name == 'foo'
+ assert not tmpl.module.foo.caller
+ assert not tmpl.module.foo.catch_kwargs
+ assert not tmpl.module.foo.catch_varargs
+ assert tmpl.module.bar.arguments == ()
+ assert tmpl.module.bar.defaults == ()
+ assert not tmpl.module.bar.caller
+ assert tmpl.module.bar.catch_kwargs
+ assert tmpl.module.bar.catch_varargs
+ assert tmpl.module.baz.caller
+
+ def test_callself(self, env_trim):
+ tmpl = env_trim.from_string('{% macro foo(x) %}{{ x }}{% if x > 1 %}|'
+ '{{ foo(x - 1) }}{% endif %}{% endmacro %}'
+ '{{ foo(5) }}')
+ assert tmpl.render() == '5|4|3|2|1'
+
+
+@pytest.mark.core_tags
+@pytest.mark.set
+class TestSet():
+
+ def test_normal(self, env_trim):
+ tmpl = env_trim.from_string('{% set foo = 1 %}{{ foo }}')
+ assert tmpl.render() == '1'
+ assert tmpl.module.foo == 1
+
+ def test_block(self, env_trim):
+ tmpl = env_trim.from_string('{% set foo %}42{% endset %}{{ foo }}')
+ assert tmpl.render() == '42'
+ assert tmpl.module.foo == u'42'
diff --git a/deps/v8_inspector/deps/jinja2/tests/test_debug.py b/deps/v8_inspector/deps/jinja2/tests/test_debug.py
new file mode 100644
index 0000000000..d8617ae08e
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/tests/test_debug.py
@@ -0,0 +1,73 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.debug
+ ~~~~~~~~~~~~~~~~~~~~~~
+
+ Tests the debug system.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import pytest
+
+import re
+
+import sys
+from traceback import format_exception
+
+from jinja2 import Environment, TemplateSyntaxError
+from traceback import format_exception
+
+
+@pytest.fixture
+def fs_env(filesystem_loader):
+ '''returns a new environment.
+ '''
+ return Environment(loader=filesystem_loader)
+
+
+@pytest.mark.debug
+class TestDebug():
+
+ def assert_traceback_matches(self, callback, expected_tb):
+ try:
+ callback()
+ except Exception as e:
+ tb = format_exception(*sys.exc_info())
+ if re.search(expected_tb.strip(), ''.join(tb)) is None:
+ assert False, ('Traceback did not match:\n\n%s\nexpected:\n%s' %
+ (''.join(tb), expected_tb))
+ else:
+ assert False, 'Expected exception'
+
+ def test_runtime_error(self, fs_env):
+ def test():
+ tmpl.render(fail=lambda: 1 / 0)
+ tmpl = fs_env.get_template('broken.html')
+ self.assert_traceback_matches(test, r'''
+ File ".*?broken.html", line 2, in (top-level template code|<module>)
+ \{\{ fail\(\) \}\}
+ File ".*debug?.pyc?", line \d+, in <lambda>
+ tmpl\.render\(fail=lambda: 1 / 0\)
+ZeroDivisionError: (int(eger)? )?division (or modulo )?by zero
+''')
+
+ def test_syntax_error(self, fs_env):
+ # XXX: the .*? is necessary for python3 which does not hide
+ # some of the stack frames we don't want to show. Not sure
+ # what's up with that, but that is not that critical. Should
+ # be fixed though.
+ self.assert_traceback_matches(lambda: fs_env.get_template('syntaxerror.html'), r'''(?sm)
+ File ".*?syntaxerror.html", line 4, in (template|<module>)
+ \{% endif %\}.*?
+(jinja2\.exceptions\.)?TemplateSyntaxError: Encountered unknown tag 'endif'. Jinja was looking for the following tags: 'endfor' or 'else'. The innermost block that needs to be closed is 'for'.
+ ''')
+
+ def test_regular_syntax_error(self, fs_env):
+ def test():
+ raise TemplateSyntaxError('wtf', 42)
+ self.assert_traceback_matches(test, r'''
+ File ".*debug.pyc?", line \d+, in test
+ raise TemplateSyntaxError\('wtf', 42\)
+(jinja2\.exceptions\.)?TemplateSyntaxError: wtf
+ line 42''')
diff --git a/deps/v8_inspector/deps/jinja2/tests/test_ext.py b/deps/v8_inspector/deps/jinja2/tests/test_ext.py
new file mode 100644
index 0000000000..8985416c9c
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/tests/test_ext.py
@@ -0,0 +1,467 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.ext
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Tests for the extensions.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import re
+import pytest
+
+from jinja2 import Environment, DictLoader, contextfunction, nodes
+from jinja2.exceptions import TemplateAssertionError
+from jinja2.ext import Extension
+from jinja2.lexer import Token, count_newlines
+from jinja2._compat import BytesIO, itervalues, text_type
+
+importable_object = 23
+
+_gettext_re = re.compile(r'_\((.*?)\)(?s)')
+
+
+i18n_templates = {
+ 'master.html': '<title>{{ page_title|default(_("missing")) }}</title>'
+ '{% block body %}{% endblock %}',
+ 'child.html': '{% extends "master.html" %}{% block body %}'
+ '{% trans %}watch out{% endtrans %}{% endblock %}',
+ 'plural.html': '{% trans user_count %}One user online{% pluralize %}'
+ '{{ user_count }} users online{% endtrans %}',
+ 'plural2.html': '{% trans user_count=get_user_count() %}{{ user_count }}s'
+ '{% pluralize %}{{ user_count }}p{% endtrans %}',
+ 'stringformat.html': '{{ _("User: %(num)s")|format(num=user_count) }}'
+}
+
+newstyle_i18n_templates = {
+ 'master.html': '<title>{{ page_title|default(_("missing")) }}</title>'
+ '{% block body %}{% endblock %}',
+ 'child.html': '{% extends "master.html" %}{% block body %}'
+ '{% trans %}watch out{% endtrans %}{% endblock %}',
+ 'plural.html': '{% trans user_count %}One user online{% pluralize %}'
+ '{{ user_count }} users online{% endtrans %}',
+ 'stringformat.html': '{{ _("User: %(num)s", num=user_count) }}',
+ 'ngettext.html': '{{ ngettext("%(num)s apple", "%(num)s apples", apples) }}',
+ 'ngettext_long.html': '{% trans num=apples %}{{ num }} apple{% pluralize %}'
+ '{{ num }} apples{% endtrans %}',
+ 'transvars1.html': '{% trans %}User: {{ num }}{% endtrans %}',
+ 'transvars2.html': '{% trans num=count %}User: {{ num }}{% endtrans %}',
+ 'transvars3.html': '{% trans count=num %}User: {{ count }}{% endtrans %}',
+ 'novars.html': '{% trans %}%(hello)s{% endtrans %}',
+ 'vars.html': '{% trans %}{{ foo }}%(foo)s{% endtrans %}',
+ 'explicitvars.html': '{% trans foo="42" %}%(foo)s{% endtrans %}'
+}
+
+
+languages = {
+ 'de': {
+ 'missing': u'fehlend',
+ 'watch out': u'pass auf',
+ 'One user online': u'Ein Benutzer online',
+ '%(user_count)s users online': u'%(user_count)s Benutzer online',
+ 'User: %(num)s': u'Benutzer: %(num)s',
+ 'User: %(count)s': u'Benutzer: %(count)s',
+ '%(num)s apple': u'%(num)s Apfel',
+ '%(num)s apples': u'%(num)s Äpfel'
+ }
+}
+
+
+@contextfunction
+def gettext(context, string):
+ language = context.get('LANGUAGE', 'en')
+ return languages.get(language, {}).get(string, string)
+
+
+@contextfunction
+def ngettext(context, s, p, n):
+ language = context.get('LANGUAGE', 'en')
+ if n != 1:
+ return languages.get(language, {}).get(p, p)
+ return languages.get(language, {}).get(s, s)
+
+
+i18n_env = Environment(
+ loader=DictLoader(i18n_templates),
+ extensions=['jinja2.ext.i18n']
+)
+i18n_env.globals.update({
+ '_': gettext,
+ 'gettext': gettext,
+ 'ngettext': ngettext
+})
+
+newstyle_i18n_env = Environment(
+ loader=DictLoader(newstyle_i18n_templates),
+ extensions=['jinja2.ext.i18n']
+)
+newstyle_i18n_env.install_gettext_callables(gettext, ngettext, newstyle=True)
+
+
+class TestExtension(Extension):
+ tags = set(['test'])
+ ext_attr = 42
+
+ def parse(self, parser):
+ return nodes.Output([self.call_method('_dump', [
+ nodes.EnvironmentAttribute('sandboxed'),
+ self.attr('ext_attr'),
+ nodes.ImportedName(__name__ + '.importable_object'),
+ nodes.ContextReference()
+ ])]).set_lineno(next(parser.stream).lineno)
+
+ def _dump(self, sandboxed, ext_attr, imported_object, context):
+ return '%s|%s|%s|%s' % (
+ sandboxed,
+ ext_attr,
+ imported_object,
+ context.blocks
+ )
+
+
+class PreprocessorExtension(Extension):
+
+ def preprocess(self, source, name, filename=None):
+ return source.replace('[[TEST]]', '({{ foo }})')
+
+
+class StreamFilterExtension(Extension):
+
+ def filter_stream(self, stream):
+ for token in stream:
+ if token.type == 'data':
+ for t in self.interpolate(token):
+ yield t
+ else:
+ yield token
+
+ def interpolate(self, token):
+ pos = 0
+ end = len(token.value)
+ lineno = token.lineno
+ while 1:
+ match = _gettext_re.search(token.value, pos)
+ if match is None:
+ break
+ value = token.value[pos:match.start()]
+ if value:
+ yield Token(lineno, 'data', value)
+ lineno += count_newlines(token.value)
+ yield Token(lineno, 'variable_begin', None)
+ yield Token(lineno, 'name', 'gettext')
+ yield Token(lineno, 'lparen', None)
+ yield Token(lineno, 'string', match.group(1))
+ yield Token(lineno, 'rparen', None)
+ yield Token(lineno, 'variable_end', None)
+ pos = match.end()
+ if pos < end:
+ yield Token(lineno, 'data', token.value[pos:])
+
+
+@pytest.mark.ext
+class TestExtensions():
+
+ def test_extend_late(self):
+ env = Environment()
+ env.add_extension('jinja2.ext.autoescape')
+ t = env.from_string(
+ '{% autoescape true %}{{ "<test>" }}{% endautoescape %}')
+ assert t.render() == '&lt;test&gt;'
+
+ def test_loop_controls(self):
+ env = Environment(extensions=['jinja2.ext.loopcontrols'])
+
+ tmpl = env.from_string('''
+ {%- for item in [1, 2, 3, 4] %}
+ {%- if item % 2 == 0 %}{% continue %}{% endif -%}
+ {{ item }}
+ {%- endfor %}''')
+ assert tmpl.render() == '13'
+
+ tmpl = env.from_string('''
+ {%- for item in [1, 2, 3, 4] %}
+ {%- if item > 2 %}{% break %}{% endif -%}
+ {{ item }}
+ {%- endfor %}''')
+ assert tmpl.render() == '12'
+
+ def test_do(self):
+ env = Environment(extensions=['jinja2.ext.do'])
+ tmpl = env.from_string('''
+ {%- set items = [] %}
+ {%- for char in "foo" %}
+ {%- do items.append(loop.index0 ~ char) %}
+ {%- endfor %}{{ items|join(', ') }}''')
+ assert tmpl.render() == '0f, 1o, 2o'
+
+ def test_with(self):
+ env = Environment(extensions=['jinja2.ext.with_'])
+ tmpl = env.from_string('''\
+ {% with a=42, b=23 -%}
+ {{ a }} = {{ b }}
+ {% endwith -%}
+ {{ a }} = {{ b }}\
+ ''')
+ assert [x.strip() for x in tmpl.render(a=1, b=2).splitlines()] \
+ == ['42 = 23', '1 = 2']
+
+ def test_extension_nodes(self):
+ env = Environment(extensions=[TestExtension])
+ tmpl = env.from_string('{% test %}')
+ assert tmpl.render() == 'False|42|23|{}'
+
+ def test_identifier(self):
+ assert TestExtension.identifier == __name__ + '.TestExtension'
+
+ def test_rebinding(self):
+ original = Environment(extensions=[TestExtension])
+ overlay = original.overlay()
+ for env in original, overlay:
+ for ext in itervalues(env.extensions):
+ assert ext.environment is env
+
+ def test_preprocessor_extension(self):
+ env = Environment(extensions=[PreprocessorExtension])
+ tmpl = env.from_string('{[[TEST]]}')
+ assert tmpl.render(foo=42) == '{(42)}'
+
+ def test_streamfilter_extension(self):
+ env = Environment(extensions=[StreamFilterExtension])
+ env.globals['gettext'] = lambda x: x.upper()
+ tmpl = env.from_string('Foo _(bar) Baz')
+ out = tmpl.render()
+ assert out == 'Foo BAR Baz'
+
+ def test_extension_ordering(self):
+ class T1(Extension):
+ priority = 1
+
+ class T2(Extension):
+ priority = 2
+ env = Environment(extensions=[T1, T2])
+ ext = list(env.iter_extensions())
+ assert ext[0].__class__ is T1
+ assert ext[1].__class__ is T2
+
+
+@pytest.mark.ext
+class TestInternationalization():
+
+ def test_trans(self):
+ tmpl = i18n_env.get_template('child.html')
+ assert tmpl.render(LANGUAGE='de') == '<title>fehlend</title>pass auf'
+
+ def test_trans_plural(self):
+ tmpl = i18n_env.get_template('plural.html')
+ assert tmpl.render(LANGUAGE='de', user_count=1) \
+ == 'Ein Benutzer online'
+ assert tmpl.render(LANGUAGE='de', user_count=2) == '2 Benutzer online'
+
+ def test_trans_plural_with_functions(self):
+ tmpl = i18n_env.get_template('plural2.html')
+
+ def get_user_count():
+ get_user_count.called += 1
+ return 1
+ get_user_count.called = 0
+ assert tmpl.render(LANGUAGE='de', get_user_count=get_user_count) \
+ == '1s'
+ assert get_user_count.called == 1
+
+ def test_complex_plural(self):
+ tmpl = i18n_env.from_string(
+ '{% trans foo=42, count=2 %}{{ count }} item{% '
+ 'pluralize count %}{{ count }} items{% endtrans %}')
+ assert tmpl.render() == '2 items'
+ pytest.raises(TemplateAssertionError, i18n_env.from_string,
+ '{% trans foo %}...{% pluralize bar %}...{% endtrans %}')
+
+ def test_trans_stringformatting(self):
+ tmpl = i18n_env.get_template('stringformat.html')
+ assert tmpl.render(LANGUAGE='de', user_count=5) == 'Benutzer: 5'
+
+ def test_extract(self):
+ from jinja2.ext import babel_extract
+ source = BytesIO('''
+ {{ gettext('Hello World') }}
+ {% trans %}Hello World{% endtrans %}
+ {% trans %}{{ users }} user{% pluralize %}{{ users }} users{% endtrans %}
+ '''.encode('ascii')) # make python 3 happy
+ assert list(babel_extract(source,
+ ('gettext', 'ngettext', '_'), [], {})) == [
+ (2, 'gettext', u'Hello World', []),
+ (3, 'gettext', u'Hello World', []),
+ (4, 'ngettext', (u'%(users)s user', u'%(users)s users', None), [])
+ ]
+
+ def test_comment_extract(self):
+ from jinja2.ext import babel_extract
+ source = BytesIO('''
+ {# trans first #}
+ {{ gettext('Hello World') }}
+ {% trans %}Hello World{% endtrans %}{# trans second #}
+ {#: third #}
+ {% trans %}{{ users }} user{% pluralize %}{{ users }} users{% endtrans %}
+ '''.encode('utf-8')) # make python 3 happy
+ assert list(babel_extract(source,
+ ('gettext', 'ngettext', '_'),
+ ['trans', ':'], {})) == [
+ (3, 'gettext', u'Hello World', ['first']),
+ (4, 'gettext', u'Hello World', ['second']),
+ (6, 'ngettext', (u'%(users)s user', u'%(users)s users', None),
+ ['third'])
+ ]
+
+
+@pytest.mark.ext
+class TestNewstyleInternationalization():
+
+ def test_trans(self):
+ tmpl = newstyle_i18n_env.get_template('child.html')
+ assert tmpl.render(LANGUAGE='de') == '<title>fehlend</title>pass auf'
+
+ def test_trans_plural(self):
+ tmpl = newstyle_i18n_env.get_template('plural.html')
+ assert tmpl.render(LANGUAGE='de', user_count=1) \
+ == 'Ein Benutzer online'
+ assert tmpl.render(LANGUAGE='de', user_count=2) == '2 Benutzer online'
+
+ def test_complex_plural(self):
+ tmpl = newstyle_i18n_env.from_string(
+ '{% trans foo=42, count=2 %}{{ count }} item{% '
+ 'pluralize count %}{{ count }} items{% endtrans %}')
+ assert tmpl.render() == '2 items'
+ pytest.raises(TemplateAssertionError, i18n_env.from_string,
+ '{% trans foo %}...{% pluralize bar %}...{% endtrans %}')
+
+ def test_trans_stringformatting(self):
+ tmpl = newstyle_i18n_env.get_template('stringformat.html')
+ assert tmpl.render(LANGUAGE='de', user_count=5) == 'Benutzer: 5'
+
+ def test_newstyle_plural(self):
+ tmpl = newstyle_i18n_env.get_template('ngettext.html')
+ assert tmpl.render(LANGUAGE='de', apples=1) == '1 Apfel'
+ assert tmpl.render(LANGUAGE='de', apples=5) == u'5 Äpfel'
+
+ def test_autoescape_support(self):
+ env = Environment(extensions=['jinja2.ext.autoescape',
+ 'jinja2.ext.i18n'])
+ env.install_gettext_callables(
+ lambda x: u'<strong>Wert: %(name)s</strong>',
+ lambda s, p, n: s, newstyle=True)
+ t = env.from_string('{% autoescape ae %}{{ gettext("foo", name='
+ '"<test>") }}{% endautoescape %}')
+ assert t.render(ae=True) == '<strong>Wert: &lt;test&gt;</strong>'
+ assert t.render(ae=False) == '<strong>Wert: <test></strong>'
+
+ def test_num_used_twice(self):
+ tmpl = newstyle_i18n_env.get_template('ngettext_long.html')
+ assert tmpl.render(apples=5, LANGUAGE='de') == u'5 Äpfel'
+
+ def test_num_called_num(self):
+ source = newstyle_i18n_env.compile('''
+ {% trans num=3 %}{{ num }} apple{% pluralize
+ %}{{ num }} apples{% endtrans %}
+ ''', raw=True)
+ # quite hacky, but the only way to properly test that. The idea is
+ # that the generated code does not pass num twice (although that
+ # would work) for better performance. This only works on the
+ # newstyle gettext of course
+ assert re.search(r"l_ngettext, u?'\%\(num\)s apple', u?'\%\(num\)s "
+ r"apples', 3", source) is not None
+
+ def test_trans_vars(self):
+ t1 = newstyle_i18n_env.get_template('transvars1.html')
+ t2 = newstyle_i18n_env.get_template('transvars2.html')
+ t3 = newstyle_i18n_env.get_template('transvars3.html')
+ assert t1.render(num=1, LANGUAGE='de') == 'Benutzer: 1'
+ assert t2.render(count=23, LANGUAGE='de') == 'Benutzer: 23'
+ assert t3.render(num=42, LANGUAGE='de') == 'Benutzer: 42'
+
+ def test_novars_vars_escaping(self):
+ t = newstyle_i18n_env.get_template('novars.html')
+ assert t.render() == '%(hello)s'
+ t = newstyle_i18n_env.get_template('vars.html')
+ assert t.render(foo='42') == '42%(foo)s'
+ t = newstyle_i18n_env.get_template('explicitvars.html')
+ assert t.render() == '%(foo)s'
+
+
+@pytest.mark.ext
+class TestAutoEscape():
+
+ def test_scoped_setting(self):
+ env = Environment(extensions=['jinja2.ext.autoescape'],
+ autoescape=True)
+ tmpl = env.from_string('''
+ {{ "<HelloWorld>" }}
+ {% autoescape false %}
+ {{ "<HelloWorld>" }}
+ {% endautoescape %}
+ {{ "<HelloWorld>" }}
+ ''')
+ assert tmpl.render().split() == \
+ [u'&lt;HelloWorld&gt;', u'<HelloWorld>', u'&lt;HelloWorld&gt;']
+
+ env = Environment(extensions=['jinja2.ext.autoescape'],
+ autoescape=False)
+ tmpl = env.from_string('''
+ {{ "<HelloWorld>" }}
+ {% autoescape true %}
+ {{ "<HelloWorld>" }}
+ {% endautoescape %}
+ {{ "<HelloWorld>" }}
+ ''')
+ assert tmpl.render().split() == \
+ [u'<HelloWorld>', u'&lt;HelloWorld&gt;', u'<HelloWorld>']
+
+ def test_nonvolatile(self):
+ env = Environment(extensions=['jinja2.ext.autoescape'],
+ autoescape=True)
+ tmpl = env.from_string('{{ {"foo": "<test>"}|xmlattr|escape }}')
+ assert tmpl.render() == ' foo="&lt;test&gt;"'
+ tmpl = env.from_string('{% autoescape false %}{{ {"foo": "<test>"}'
+ '|xmlattr|escape }}{% endautoescape %}')
+ assert tmpl.render() == ' foo=&#34;&amp;lt;test&amp;gt;&#34;'
+
+ def test_volatile(self):
+ env = Environment(extensions=['jinja2.ext.autoescape'],
+ autoescape=True)
+ tmpl = env.from_string('{% autoescape foo %}{{ {"foo": "<test>"}'
+ '|xmlattr|escape }}{% endautoescape %}')
+ assert tmpl.render(foo=False) == ' foo=&#34;&amp;lt;test&amp;gt;&#34;'
+ assert tmpl.render(foo=True) == ' foo="&lt;test&gt;"'
+
+ def test_scoping(self):
+ env = Environment(extensions=['jinja2.ext.autoescape'])
+ tmpl = env.from_string(
+ '{% autoescape true %}{% set x = "<x>" %}{{ x }}'
+ '{% endautoescape %}{{ x }}{{ "<y>" }}')
+ assert tmpl.render(x=1) == '&lt;x&gt;1<y>'
+
+ def test_volatile_scoping(self):
+ env = Environment(extensions=['jinja2.ext.autoescape'])
+ tmplsource = '''
+ {% autoescape val %}
+ {% macro foo(x) %}
+ [{{ x }}]
+ {% endmacro %}
+ {{ foo().__class__.__name__ }}
+ {% endautoescape %}
+ {{ '<testing>' }}
+ '''
+ tmpl = env.from_string(tmplsource)
+ assert tmpl.render(val=True).split()[0] == 'Markup'
+ assert tmpl.render(val=False).split()[0] == text_type.__name__
+
+ # looking at the source we should see <testing> there in raw
+ # (and then escaped as well)
+ env = Environment(extensions=['jinja2.ext.autoescape'])
+ pysource = env.compile(tmplsource, raw=True)
+ assert '<testing>\\n' in pysource
+
+ env = Environment(extensions=['jinja2.ext.autoescape'],
+ autoescape=True)
+ pysource = env.compile(tmplsource, raw=True)
+ assert '&lt;testing&gt;\\n' in pysource
diff --git a/deps/v8_inspector/deps/jinja2/tests/test_filters.py b/deps/v8_inspector/deps/jinja2/tests/test_filters.py
new file mode 100644
index 0000000000..741ef341b1
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/tests/test_filters.py
@@ -0,0 +1,558 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.filters
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Tests for the jinja filters.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import pytest
+from jinja2 import Markup, Environment
+from jinja2._compat import text_type, implements_to_string
+
+
+@pytest.mark.filter
+class TestFilter():
+
+ def test_filter_calling(self, env):
+ rv = env.call_filter('sum', [1, 2, 3])
+ assert rv == 6
+
+ def test_capitalize(self, env):
+ tmpl = env.from_string('{{ "foo bar"|capitalize }}')
+ assert tmpl.render() == 'Foo bar'
+
+ def test_center(self, env):
+ tmpl = env.from_string('{{ "foo"|center(9) }}')
+ assert tmpl.render() == ' foo '
+
+ def test_default(self, env):
+ tmpl = env.from_string(
+ "{{ missing|default('no') }}|{{ false|default('no') }}|"
+ "{{ false|default('no', true) }}|{{ given|default('no') }}"
+ )
+ assert tmpl.render(given='yes') == 'no|False|no|yes'
+
+ def test_dictsort(self, env):
+ tmpl = env.from_string(
+ '{{ foo|dictsort }}|'
+ '{{ foo|dictsort(true) }}|'
+ '{{ foo|dictsort(false, "value") }}'
+ )
+ out = tmpl.render(foo={"aa": 0, "b": 1, "c": 2, "AB": 3})
+ assert out == ("[('aa', 0), ('AB', 3), ('b', 1), ('c', 2)]|"
+ "[('AB', 3), ('aa', 0), ('b', 1), ('c', 2)]|"
+ "[('aa', 0), ('b', 1), ('c', 2), ('AB', 3)]")
+
+ def test_batch(self, env):
+ tmpl = env.from_string("{{ foo|batch(3)|list }}|"
+ "{{ foo|batch(3, 'X')|list }}")
+ out = tmpl.render(foo=list(range(10)))
+ assert out == ("[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]|"
+ "[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 'X', 'X']]")
+
+ def test_slice(self, env):
+ tmpl = env.from_string('{{ foo|slice(3)|list }}|'
+ '{{ foo|slice(3, "X")|list }}')
+ out = tmpl.render(foo=list(range(10)))
+ assert out == ("[[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]]|"
+ "[[0, 1, 2, 3], [4, 5, 6, 'X'], [7, 8, 9, 'X']]")
+
+ def test_escape(self, env):
+ tmpl = env.from_string('''{{ '<">&'|escape }}''')
+ out = tmpl.render()
+ assert out == '&lt;&#34;&gt;&amp;'
+
+ def test_striptags(self, env):
+ tmpl = env.from_string('''{{ foo|striptags }}''')
+ out = tmpl.render(foo=' <p>just a small \n <a href="#">'
+ 'example</a> link</p>\n<p>to a webpage</p> '
+ '<!-- <p>and some commented stuff</p> -->')
+ assert out == 'just a small example link to a webpage'
+
+ def test_filesizeformat(self, env):
+ tmpl = env.from_string(
+ '{{ 100|filesizeformat }}|'
+ '{{ 1000|filesizeformat }}|'
+ '{{ 1000000|filesizeformat }}|'
+ '{{ 1000000000|filesizeformat }}|'
+ '{{ 1000000000000|filesizeformat }}|'
+ '{{ 100|filesizeformat(true) }}|'
+ '{{ 1000|filesizeformat(true) }}|'
+ '{{ 1000000|filesizeformat(true) }}|'
+ '{{ 1000000000|filesizeformat(true) }}|'
+ '{{ 1000000000000|filesizeformat(true) }}'
+ )
+ out = tmpl.render()
+ assert out == (
+ '100 Bytes|1.0 kB|1.0 MB|1.0 GB|1.0 TB|100 Bytes|'
+ '1000 Bytes|976.6 KiB|953.7 MiB|931.3 GiB'
+ )
+
+ def test_filesizeformat_issue59(self, env):
+ tmpl = env.from_string(
+ '{{ 300|filesizeformat }}|'
+ '{{ 3000|filesizeformat }}|'
+ '{{ 3000000|filesizeformat }}|'
+ '{{ 3000000000|filesizeformat }}|'
+ '{{ 3000000000000|filesizeformat }}|'
+ '{{ 300|filesizeformat(true) }}|'
+ '{{ 3000|filesizeformat(true) }}|'
+ '{{ 3000000|filesizeformat(true) }}'
+ )
+ out = tmpl.render()
+ assert out == (
+ '300 Bytes|3.0 kB|3.0 MB|3.0 GB|3.0 TB|300 Bytes|'
+ '2.9 KiB|2.9 MiB'
+ )
+
+ def test_first(self, env):
+ tmpl = env.from_string('{{ foo|first }}')
+ out = tmpl.render(foo=list(range(10)))
+ assert out == '0'
+
+ def test_float(self, env):
+ tmpl = env.from_string('{{ "42"|float }}|'
+ '{{ "ajsghasjgd"|float }}|'
+ '{{ "32.32"|float }}')
+ out = tmpl.render()
+ assert out == '42.0|0.0|32.32'
+
+ def test_format(self, env):
+ tmpl = env.from_string('''{{ "%s|%s"|format("a", "b") }}''')
+ out = tmpl.render()
+ assert out == 'a|b'
+
+ def test_indent(self, env):
+ tmpl = env.from_string('{{ foo|indent(2) }}|{{ foo|indent(2, true) }}')
+ text = '\n'.join([' '.join(['foo', 'bar'] * 2)] * 2)
+ out = tmpl.render(foo=text)
+ assert out == ('foo bar foo bar\n foo bar foo bar| '
+ 'foo bar foo bar\n foo bar foo bar')
+
+ def test_int(self, env):
+ tmpl = env.from_string('{{ "42"|int }}|{{ "ajsghasjgd"|int }}|'
+ '{{ "32.32"|int }}|{{ "0x4d32"|int(0, 16) }}|'
+ '{{ "011"|int(0, 8)}}|{{ "0x33FU"|int(0, 16) }}')
+ out = tmpl.render()
+ assert out == '42|0|32|19762|9|0'
+
+ def test_join(self, env):
+ tmpl = env.from_string('{{ [1, 2, 3]|join("|") }}')
+ out = tmpl.render()
+ assert out == '1|2|3'
+
+ env2 = Environment(autoescape=True)
+ tmpl = env2.from_string(
+ '{{ ["<foo>", "<span>foo</span>"|safe]|join }}')
+ assert tmpl.render() == '&lt;foo&gt;<span>foo</span>'
+
+ def test_join_attribute(self, env):
+ class User(object):
+ def __init__(self, username):
+ self.username = username
+ tmpl = env.from_string('''{{ users|join(', ', 'username') }}''')
+ assert tmpl.render(users=map(User, ['foo', 'bar'])) == 'foo, bar'
+
+ def test_last(self, env):
+ tmpl = env.from_string('''{{ foo|last }}''')
+ out = tmpl.render(foo=list(range(10)))
+ assert out == '9'
+
+ def test_length(self, env):
+ tmpl = env.from_string('''{{ "hello world"|length }}''')
+ out = tmpl.render()
+ assert out == '11'
+
+ def test_lower(self, env):
+ tmpl = env.from_string('''{{ "FOO"|lower }}''')
+ out = tmpl.render()
+ assert out == 'foo'
+
+ def test_pprint(self, env):
+ from pprint import pformat
+ tmpl = env.from_string('''{{ data|pprint }}''')
+ data = list(range(1000))
+ assert tmpl.render(data=data) == pformat(data)
+
+ def test_random(self, env):
+ tmpl = env.from_string('''{{ seq|random }}''')
+ seq = list(range(100))
+ for _ in range(10):
+ assert int(tmpl.render(seq=seq)) in seq
+
+ def test_reverse(self, env):
+ tmpl = env.from_string('{{ "foobar"|reverse|join }}|'
+ '{{ [1, 2, 3]|reverse|list }}')
+ assert tmpl.render() == 'raboof|[3, 2, 1]'
+
+ def test_string(self, env):
+ x = [1, 2, 3, 4, 5]
+ tmpl = env.from_string('''{{ obj|string }}''')
+ assert tmpl.render(obj=x) == text_type(x)
+
+ def test_title(self, env):
+ tmpl = env.from_string('''{{ "foo bar"|title }}''')
+ assert tmpl.render() == "Foo Bar"
+ tmpl = env.from_string('''{{ "foo's bar"|title }}''')
+ assert tmpl.render() == "Foo's Bar"
+ tmpl = env.from_string('''{{ "foo bar"|title }}''')
+ assert tmpl.render() == "Foo Bar"
+ tmpl = env.from_string('''{{ "f bar f"|title }}''')
+ assert tmpl.render() == "F Bar F"
+ tmpl = env.from_string('''{{ "foo-bar"|title }}''')
+ assert tmpl.render() == "Foo-Bar"
+ tmpl = env.from_string('''{{ "foo\tbar"|title }}''')
+ assert tmpl.render() == "Foo\tBar"
+ tmpl = env.from_string('''{{ "FOO\tBAR"|title }}''')
+ assert tmpl.render() == "Foo\tBar"
+
+ class Foo:
+ def __str__(self):
+ return 'foo-bar'
+
+ tmpl = env.from_string('''{{ data|title }}''')
+ out = tmpl.render(data=Foo())
+ assert out == 'Foo-Bar'
+
+ def test_truncate(self, env):
+ tmpl = env.from_string(
+ '{{ data|truncate(15, true, ">>>") }}|'
+ '{{ data|truncate(15, false, ">>>") }}|'
+ '{{ smalldata|truncate(15) }}'
+ )
+ out = tmpl.render(data='foobar baz bar' * 1000,
+ smalldata='foobar baz bar')
+ msg = 'Current output: %s' % out
+ assert out == 'foobar baz b>>>|foobar baz >>>|foobar baz bar', msg
+
+ def test_truncate_very_short(self, env):
+ tmpl = env.from_string(
+ '{{ "foo bar baz"|truncate(9) }}|'
+ '{{ "foo bar baz"|truncate(9, true) }}'
+ )
+ out = tmpl.render()
+ assert out == 'foo ...|foo ba...', out
+
+ def test_truncate_end_length(self, env):
+ tmpl = env.from_string('{{ "Joel is a slug"|truncate(9, true) }}')
+ out = tmpl.render()
+ assert out == 'Joel i...', 'Current output: %s' % out
+
+ def test_upper(self, env):
+ tmpl = env.from_string('{{ "foo"|upper }}')
+ assert tmpl.render() == 'FOO'
+
+ def test_urlize(self, env):
+ tmpl = env.from_string(
+ '{{ "foo http://www.example.com/ bar"|urlize }}')
+ assert tmpl.render() == 'foo <a href="http://www.example.com/">'\
+ 'http://www.example.com/</a> bar'
+
+ def test_urlize_target_parameter(self, env):
+ tmpl = env.from_string(
+ '{{ "foo http://www.example.com/ bar"|urlize(target="_blank") }}'
+ )
+ assert tmpl.render() \
+ == 'foo <a href="http://www.example.com/" target="_blank">'\
+ 'http://www.example.com/</a> bar'
+ tmpl = env.from_string(
+ '{{ "foo http://www.example.com/ bar"|urlize(target=42) }}'
+ )
+ assert tmpl.render() == 'foo <a href="http://www.example.com/">'\
+ 'http://www.example.com/</a> bar'
+
+ def test_wordcount(self, env):
+ tmpl = env.from_string('{{ "foo bar baz"|wordcount }}')
+ assert tmpl.render() == '3'
+
+ def test_block(self, env):
+ tmpl = env.from_string(
+ '{% filter lower|escape %}<HEHE>{% endfilter %}'
+ )
+ assert tmpl.render() == '&lt;hehe&gt;'
+
+ def test_chaining(self, env):
+ tmpl = env.from_string(
+ '''{{ ['<foo>', '<bar>']|first|upper|escape }}'''
+ )
+ assert tmpl.render() == '&lt;FOO&gt;'
+
+ def test_sum(self, env):
+ tmpl = env.from_string('''{{ [1, 2, 3, 4, 5, 6]|sum }}''')
+ assert tmpl.render() == '21'
+
+ def test_sum_attributes(self, env):
+ tmpl = env.from_string('''{{ values|sum('value') }}''')
+ assert tmpl.render(values=[
+ {'value': 23},
+ {'value': 1},
+ {'value': 18},
+ ]) == '42'
+
+ def test_sum_attributes_nested(self, env):
+ tmpl = env.from_string('''{{ values|sum('real.value') }}''')
+ assert tmpl.render(values=[
+ {'real': {'value': 23}},
+ {'real': {'value': 1}},
+ {'real': {'value': 18}},
+ ]) == '42'
+
+ def test_sum_attributes_tuple(self, env):
+ tmpl = env.from_string('''{{ values.items()|sum('1') }}''')
+ assert tmpl.render(values={
+ 'foo': 23,
+ 'bar': 1,
+ 'baz': 18,
+ }) == '42'
+
+ def test_abs(self, env):
+ tmpl = env.from_string('''{{ -1|abs }}|{{ 1|abs }}''')
+ assert tmpl.render() == '1|1', tmpl.render()
+
+ def test_round_positive(self, env):
+ tmpl = env.from_string('{{ 2.7|round }}|{{ 2.1|round }}|'
+ "{{ 2.1234|round(3, 'floor') }}|"
+ "{{ 2.1|round(0, 'ceil') }}")
+ assert tmpl.render() == '3.0|2.0|2.123|3.0', tmpl.render()
+
+ def test_round_negative(self, env):
+ tmpl = env.from_string('{{ 21.3|round(-1)}}|'
+ "{{ 21.3|round(-1, 'ceil')}}|"
+ "{{ 21.3|round(-1, 'floor')}}")
+ assert tmpl.render() == '20.0|30.0|20.0', tmpl.render()
+
+ def test_xmlattr(self, env):
+ tmpl = env.from_string(
+ "{{ {'foo': 42, 'bar': 23, 'fish': none, "
+ "'spam': missing, 'blub:blub': '<?>'}|xmlattr }}")
+ out = tmpl.render().split()
+ assert len(out) == 3
+ assert 'foo="42"' in out
+ assert 'bar="23"' in out
+ assert 'blub:blub="&lt;?&gt;"' in out
+
+ def test_sort1(self, env):
+ tmpl = env.from_string(
+ '{{ [2, 3, 1]|sort }}|{{ [2, 3, 1]|sort(true) }}')
+ assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]'
+
+ def test_sort2(self, env):
+ tmpl = env.from_string('{{ "".join(["c", "A", "b", "D"]|sort) }}')
+ assert tmpl.render() == 'AbcD'
+
+ def test_sort3(self, env):
+ tmpl = env.from_string('''{{ ['foo', 'Bar', 'blah']|sort }}''')
+ assert tmpl.render() == "['Bar', 'blah', 'foo']"
+
+ def test_sort4(self, env):
+ @implements_to_string
+ class Magic(object):
+ def __init__(self, value):
+ self.value = value
+
+ def __str__(self):
+ return text_type(self.value)
+ tmpl = env.from_string('''{{ items|sort(attribute='value')|join }}''')
+ assert tmpl.render(items=map(Magic, [3, 2, 4, 1])) == '1234'
+
+ def test_groupby(self, env):
+ tmpl = env.from_string('''
+ {%- for grouper, list in [{'foo': 1, 'bar': 2},
+ {'foo': 2, 'bar': 3},
+ {'foo': 1, 'bar': 1},
+ {'foo': 3, 'bar': 4}]|groupby('foo') -%}
+ {{ grouper }}{% for x in list %}: {{ x.foo }}, {{ x.bar }}{% endfor %}|
+ {%- endfor %}''')
+ assert tmpl.render().split('|') == [
+ "1: 1, 2: 1, 1",
+ "2: 2, 3",
+ "3: 3, 4",
+ ""
+ ]
+
+ def test_groupby_tuple_index(self, env):
+ tmpl = env.from_string('''
+ {%- for grouper, list in [('a', 1), ('a', 2), ('b', 1)]|groupby(0) -%}
+ {{ grouper }}{% for x in list %}:{{ x.1 }}{% endfor %}|
+ {%- endfor %}''')
+ assert tmpl.render() == 'a:1:2|b:1|'
+
+ def test_groupby_multidot(self, env):
+ class Date(object):
+ def __init__(self, day, month, year):
+ self.day = day
+ self.month = month
+ self.year = year
+
+ class Article(object):
+ def __init__(self, title, *date):
+ self.date = Date(*date)
+ self.title = title
+ articles = [
+ Article('aha', 1, 1, 1970),
+ Article('interesting', 2, 1, 1970),
+ Article('really?', 3, 1, 1970),
+ Article('totally not', 1, 1, 1971)
+ ]
+ tmpl = env.from_string('''
+ {%- for year, list in articles|groupby('date.year') -%}
+ {{ year }}{% for x in list %}[{{ x.title }}]{% endfor %}|
+ {%- endfor %}''')
+ assert tmpl.render(articles=articles).split('|') == [
+ '1970[aha][interesting][really?]',
+ '1971[totally not]',
+ ''
+ ]
+
+ def test_filtertag(self, env):
+ tmpl = env.from_string("{% filter upper|replace('FOO', 'foo') %}"
+ "foobar{% endfilter %}")
+ assert tmpl.render() == 'fooBAR'
+
+ def test_replace(self, env):
+ env = Environment()
+ tmpl = env.from_string('{{ string|replace("o", 42) }}')
+ assert tmpl.render(string='<foo>') == '<f4242>'
+ env = Environment(autoescape=True)
+ tmpl = env.from_string('{{ string|replace("o", 42) }}')
+ assert tmpl.render(string='<foo>') == '&lt;f4242&gt;'
+ tmpl = env.from_string('{{ string|replace("<", 42) }}')
+ assert tmpl.render(string='<foo>') == '42foo&gt;'
+ tmpl = env.from_string('{{ string|replace("o", ">x<") }}')
+ assert tmpl.render(string=Markup('foo')) == 'f&gt;x&lt;&gt;x&lt;'
+
+ def test_forceescape(self, env):
+ tmpl = env.from_string('{{ x|forceescape }}')
+ assert tmpl.render(x=Markup('<div />')) == u'&lt;div /&gt;'
+
+ def test_safe(self, env):
+ env = Environment(autoescape=True)
+ tmpl = env.from_string('{{ "<div>foo</div>"|safe }}')
+ assert tmpl.render() == '<div>foo</div>'
+ tmpl = env.from_string('{{ "<div>foo</div>" }}')
+ assert tmpl.render() == '&lt;div&gt;foo&lt;/div&gt;'
+
+ def test_urlencode(self, env):
+ env = Environment(autoescape=True)
+ tmpl = env.from_string('{{ "Hello, world!"|urlencode }}')
+ assert tmpl.render() == 'Hello%2C%20world%21'
+ tmpl = env.from_string('{{ o|urlencode }}')
+ assert tmpl.render(o=u"Hello, world\u203d") \
+ == "Hello%2C%20world%E2%80%BD"
+ assert tmpl.render(o=(("f", 1),)) == "f=1"
+ assert tmpl.render(o=(('f', 1), ("z", 2))) == "f=1&amp;z=2"
+ assert tmpl.render(o=((u"\u203d", 1),)) == "%E2%80%BD=1"
+ assert tmpl.render(o={u"\u203d": 1}) == "%E2%80%BD=1"
+ assert tmpl.render(o={0: 1}) == "0=1"
+
+ def test_simple_map(self, env):
+ env = Environment()
+ tmpl = env.from_string('{{ ["1", "2", "3"]|map("int")|sum }}')
+ assert tmpl.render() == '6'
+
+ def test_attribute_map(self, env):
+ class User(object):
+ def __init__(self, name):
+ self.name = name
+ env = Environment()
+ users = [
+ User('john'),
+ User('jane'),
+ User('mike'),
+ ]
+ tmpl = env.from_string('{{ users|map(attribute="name")|join("|") }}')
+ assert tmpl.render(users=users) == 'john|jane|mike'
+
+ def test_empty_map(self, env):
+ env = Environment()
+ tmpl = env.from_string('{{ none|map("upper")|list }}')
+ assert tmpl.render() == '[]'
+
+ def test_simple_select(self, env):
+ env = Environment()
+ tmpl = env.from_string('{{ [1, 2, 3, 4, 5]|select("odd")|join("|") }}')
+ assert tmpl.render() == '1|3|5'
+
+ def test_bool_select(self, env):
+ env = Environment()
+ tmpl = env.from_string(
+ '{{ [none, false, 0, 1, 2, 3, 4, 5]|select|join("|") }}'
+ )
+ assert tmpl.render() == '1|2|3|4|5'
+
+ def test_simple_reject(self, env):
+ env = Environment()
+ tmpl = env.from_string('{{ [1, 2, 3, 4, 5]|reject("odd")|join("|") }}')
+ assert tmpl.render() == '2|4'
+
+ def test_bool_reject(self, env):
+ env = Environment()
+ tmpl = env.from_string(
+ '{{ [none, false, 0, 1, 2, 3, 4, 5]|reject|join("|") }}'
+ )
+ assert tmpl.render() == 'None|False|0'
+
+ def test_simple_select_attr(self, env):
+ class User(object):
+ def __init__(self, name, is_active):
+ self.name = name
+ self.is_active = is_active
+ env = Environment()
+ users = [
+ User('john', True),
+ User('jane', True),
+ User('mike', False),
+ ]
+ tmpl = env.from_string(
+ '{{ users|selectattr("is_active")|'
+ 'map(attribute="name")|join("|") }}'
+ )
+ assert tmpl.render(users=users) == 'john|jane'
+
+ def test_simple_reject_attr(self, env):
+ class User(object):
+ def __init__(self, name, is_active):
+ self.name = name
+ self.is_active = is_active
+ env = Environment()
+ users = [
+ User('john', True),
+ User('jane', True),
+ User('mike', False),
+ ]
+ tmpl = env.from_string('{{ users|rejectattr("is_active")|'
+ 'map(attribute="name")|join("|") }}')
+ assert tmpl.render(users=users) == 'mike'
+
+ def test_func_select_attr(self, env):
+ class User(object):
+ def __init__(self, id, name):
+ self.id = id
+ self.name = name
+ env = Environment()
+ users = [
+ User(1, 'john'),
+ User(2, 'jane'),
+ User(3, 'mike'),
+ ]
+ tmpl = env.from_string('{{ users|selectattr("id", "odd")|'
+ 'map(attribute="name")|join("|") }}')
+ assert tmpl.render(users=users) == 'john|mike'
+
+ def test_func_reject_attr(self, env):
+ class User(object):
+ def __init__(self, id, name):
+ self.id = id
+ self.name = name
+ env = Environment()
+ users = [
+ User(1, 'john'),
+ User(2, 'jane'),
+ User(3, 'mike'),
+ ]
+ tmpl = env.from_string('{{ users|rejectattr("id", "odd")|'
+ 'map(attribute="name")|join("|") }}')
+ assert tmpl.render(users=users) == 'jane'
diff --git a/deps/v8_inspector/deps/jinja2/tests/test_imports.py b/deps/v8_inspector/deps/jinja2/tests/test_imports.py
new file mode 100644
index 0000000000..643c995c6e
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/tests/test_imports.py
@@ -0,0 +1,148 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.imports
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Tests the import features (with includes).
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import pytest
+
+from jinja2 import Environment, DictLoader
+from jinja2.exceptions import TemplateNotFound, TemplatesNotFound
+
+
+@pytest.fixture
+def test_env():
+ env = Environment(loader=DictLoader(dict(
+ module='{% macro test() %}[{{ foo }}|{{ bar }}]{% endmacro %}',
+ header='[{{ foo }}|{{ 23 }}]',
+ o_printer='({{ o }})'
+ )))
+ env.globals['bar'] = 23
+ return env
+
+
+@pytest.mark.imports
+class TestImports():
+
+ def test_context_imports(self, test_env):
+ t = test_env.from_string('{% import "module" as m %}{{ m.test() }}')
+ assert t.render(foo=42) == '[|23]'
+ t = test_env.from_string(
+ '{% import "module" as m without context %}{{ m.test() }}'
+ )
+ assert t.render(foo=42) == '[|23]'
+ t = test_env.from_string(
+ '{% import "module" as m with context %}{{ m.test() }}'
+ )
+ assert t.render(foo=42) == '[42|23]'
+ t = test_env.from_string('{% from "module" import test %}{{ test() }}')
+ assert t.render(foo=42) == '[|23]'
+ t = test_env.from_string(
+ '{% from "module" import test without context %}{{ test() }}'
+ )
+ assert t.render(foo=42) == '[|23]'
+ t = test_env.from_string(
+ '{% from "module" import test with context %}{{ test() }}'
+ )
+ assert t.render(foo=42) == '[42|23]'
+
+ def test_trailing_comma(self, test_env):
+ test_env.from_string('{% from "foo" import bar, baz with context %}')
+ test_env.from_string('{% from "foo" import bar, baz, with context %}')
+ test_env.from_string('{% from "foo" import bar, with context %}')
+ test_env.from_string('{% from "foo" import bar, with, context %}')
+ test_env.from_string('{% from "foo" import bar, with with context %}')
+
+ def test_exports(self, test_env):
+ m = test_env.from_string('''
+ {% macro toplevel() %}...{% endmacro %}
+ {% macro __private() %}...{% endmacro %}
+ {% set variable = 42 %}
+ {% for item in [1] %}
+ {% macro notthere() %}{% endmacro %}
+ {% endfor %}
+ ''').module
+ assert m.toplevel() == '...'
+ assert not hasattr(m, '__missing')
+ assert m.variable == 42
+ assert not hasattr(m, 'notthere')
+
+
+@pytest.mark.imports
+@pytest.mark.includes
+class TestIncludes():
+
+ def test_context_include(self, test_env):
+ t = test_env.from_string('{% include "header" %}')
+ assert t.render(foo=42) == '[42|23]'
+ t = test_env.from_string('{% include "header" with context %}')
+ assert t.render(foo=42) == '[42|23]'
+ t = test_env.from_string('{% include "header" without context %}')
+ assert t.render(foo=42) == '[|23]'
+
+ def test_choice_includes(self, test_env):
+ t = test_env.from_string('{% include ["missing", "header"] %}')
+ assert t.render(foo=42) == '[42|23]'
+
+ t = test_env.from_string(
+ '{% include ["missing", "missing2"] ignore missing %}'
+ )
+ assert t.render(foo=42) == ''
+
+ t = test_env.from_string('{% include ["missing", "missing2"] %}')
+ pytest.raises(TemplateNotFound, t.render)
+ try:
+ t.render()
+ except TemplatesNotFound as e:
+ assert e.templates == ['missing', 'missing2']
+ assert e.name == 'missing2'
+ else:
+ assert False, 'thou shalt raise'
+
+ def test_includes(t, **ctx):
+ ctx['foo'] = 42
+ assert t.render(ctx) == '[42|23]'
+
+ t = test_env.from_string('{% include ["missing", "header"] %}')
+ test_includes(t)
+ t = test_env.from_string('{% include x %}')
+ test_includes(t, x=['missing', 'header'])
+ t = test_env.from_string('{% include [x, "header"] %}')
+ test_includes(t, x='missing')
+ t = test_env.from_string('{% include x %}')
+ test_includes(t, x='header')
+ t = test_env.from_string('{% include x %}')
+ test_includes(t, x='header')
+ t = test_env.from_string('{% include [x] %}')
+ test_includes(t, x='header')
+
+ def test_include_ignoring_missing(self, test_env):
+ t = test_env.from_string('{% include "missing" %}')
+ pytest.raises(TemplateNotFound, t.render)
+ for extra in '', 'with context', 'without context':
+ t = test_env.from_string('{% include "missing" ignore missing ' +
+ extra + ' %}')
+ assert t.render() == ''
+
+ def test_context_include_with_overrides(self, test_env):
+ env = Environment(loader=DictLoader(dict(
+ main="{% for item in [1, 2, 3] %}{% include 'item' %}{% endfor %}",
+ item="{{ item }}"
+ )))
+ assert env.get_template("main").render() == "123"
+
+ def test_unoptimized_scopes(self, test_env):
+ t = test_env.from_string("""
+ {% macro outer(o) %}
+ {% macro inner() %}
+ {% include "o_printer" %}
+ {% endmacro %}
+ {{ inner() }}
+ {% endmacro %}
+ {{ outer("FOO") }}
+ """)
+ assert t.render().strip() == '(FOO)'
diff --git a/deps/v8_inspector/deps/jinja2/tests/test_inheritance.py b/deps/v8_inspector/deps/jinja2/tests/test_inheritance.py
new file mode 100644
index 0000000000..1cb7390441
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/tests/test_inheritance.py
@@ -0,0 +1,248 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.inheritance
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Tests the template inheritance feature.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import pytest
+
+from jinja2 import Environment, DictLoader, TemplateError
+
+
+LAYOUTTEMPLATE = '''\
+|{% block block1 %}block 1 from layout{% endblock %}
+|{% block block2 %}block 2 from layout{% endblock %}
+|{% block block3 %}
+{% block block4 %}nested block 4 from layout{% endblock %}
+{% endblock %}|'''
+
+LEVEL1TEMPLATE = '''\
+{% extends "layout" %}
+{% block block1 %}block 1 from level1{% endblock %}'''
+
+LEVEL2TEMPLATE = '''\
+{% extends "level1" %}
+{% block block2 %}{% block block5 %}nested block 5 from level2{%
+endblock %}{% endblock %}'''
+
+LEVEL3TEMPLATE = '''\
+{% extends "level2" %}
+{% block block5 %}block 5 from level3{% endblock %}
+{% block block4 %}block 4 from level3{% endblock %}
+'''
+
+LEVEL4TEMPLATE = '''\
+{% extends "level3" %}
+{% block block3 %}block 3 from level4{% endblock %}
+'''
+
+WORKINGTEMPLATE = '''\
+{% extends "layout" %}
+{% block block1 %}
+ {% if false %}
+ {% block block2 %}
+ this should workd
+ {% endblock %}
+ {% endif %}
+{% endblock %}
+'''
+
+DOUBLEEXTENDS = '''\
+{% extends "layout" %}
+{% extends "layout" %}
+{% block block1 %}
+ {% if false %}
+ {% block block2 %}
+ this should workd
+ {% endblock %}
+ {% endif %}
+{% endblock %}
+'''
+
+
+@pytest.fixture
+def env():
+ return Environment(loader=DictLoader({
+ 'layout': LAYOUTTEMPLATE,
+ 'level1': LEVEL1TEMPLATE,
+ 'level2': LEVEL2TEMPLATE,
+ 'level3': LEVEL3TEMPLATE,
+ 'level4': LEVEL4TEMPLATE,
+ 'working': WORKINGTEMPLATE,
+ 'doublee': DOUBLEEXTENDS,
+ }), trim_blocks=True)
+
+
+@pytest.mark.inheritance
+class TestInheritance():
+
+ def test_layout(self, env):
+ tmpl = env.get_template('layout')
+ assert tmpl.render() == ('|block 1 from layout|block 2 from '
+ 'layout|nested block 4 from layout|')
+
+ def test_level1(self, env):
+ tmpl = env.get_template('level1')
+ assert tmpl.render() == ('|block 1 from level1|block 2 from '
+ 'layout|nested block 4 from layout|')
+
+ def test_level2(self, env):
+ tmpl = env.get_template('level2')
+ assert tmpl.render() == ('|block 1 from level1|nested block 5 from '
+ 'level2|nested block 4 from layout|')
+
+ def test_level3(self, env):
+ tmpl = env.get_template('level3')
+ assert tmpl.render() == ('|block 1 from level1|block 5 from level3|'
+ 'block 4 from level3|')
+
+ def test_level4(self, env):
+ tmpl = env.get_template('level4')
+ assert tmpl.render() == ('|block 1 from level1|block 5 from '
+ 'level3|block 3 from level4|')
+
+ def test_super(self, env):
+ env = Environment(loader=DictLoader({
+ 'a': '{% block intro %}INTRO{% endblock %}|'
+ 'BEFORE|{% block data %}INNER{% endblock %}|AFTER',
+ 'b': '{% extends "a" %}{% block data %}({{ '
+ 'super() }}){% endblock %}',
+ 'c': '{% extends "b" %}{% block intro %}--{{ '
+ 'super() }}--{% endblock %}\n{% block data '
+ '%}[{{ super() }}]{% endblock %}'
+ }))
+ tmpl = env.get_template('c')
+ assert tmpl.render() == '--INTRO--|BEFORE|[(INNER)]|AFTER'
+
+ def test_working(self, env):
+ tmpl = env.get_template('working')
+
+ def test_reuse_blocks(self, env):
+ tmpl = env.from_string('{{ self.foo() }}|{% block foo %}42'
+ '{% endblock %}|{{ self.foo() }}')
+ assert tmpl.render() == '42|42|42'
+
+ def test_preserve_blocks(self, env):
+ env = Environment(loader=DictLoader({
+ 'a': '{% if false %}{% block x %}A{% endblock %}'
+ '{% endif %}{{ self.x() }}',
+ 'b': '{% extends "a" %}{% block x %}B{{ super() }}{% endblock %}'
+ }))
+ tmpl = env.get_template('b')
+ assert tmpl.render() == 'BA'
+
+ def test_dynamic_inheritance(self, env):
+ env = Environment(loader=DictLoader({
+ 'master1': 'MASTER1{% block x %}{% endblock %}',
+ 'master2': 'MASTER2{% block x %}{% endblock %}',
+ 'child': '{% extends master %}{% block x %}CHILD{% endblock %}'
+ }))
+ tmpl = env.get_template('child')
+ for m in range(1, 3):
+ assert tmpl.render(master='master%d' % m) == 'MASTER%dCHILD' % m
+
+ def test_multi_inheritance(self, env):
+ env = Environment(loader=DictLoader({
+ 'master1': 'MASTER1{% block x %}{% endblock %}',
+ 'master2': 'MASTER2{% block x %}{% endblock %}',
+ 'child':
+ '''{% if master %}{% extends master %}{% else %}{% extends
+ 'master1' %}{% endif %}{% block x %}CHILD{% endblock %}'''
+ }))
+ tmpl = env.get_template('child')
+ assert tmpl.render(master='master2') == 'MASTER2CHILD'
+ assert tmpl.render(master='master1') == 'MASTER1CHILD'
+ assert tmpl.render() == 'MASTER1CHILD'
+
+ def test_scoped_block(self, env):
+ env = Environment(loader=DictLoader({
+ 'master.html': '{% for item in seq %}[{% block item scoped %}'
+ '{% endblock %}]{% endfor %}'
+ }))
+ t = env.from_string('{% extends "master.html" %}{% block item %}'
+ '{{ item }}{% endblock %}')
+ assert t.render(seq=list(range(5))) == '[0][1][2][3][4]'
+
+ def test_super_in_scoped_block(self, env):
+ env = Environment(loader=DictLoader({
+ 'master.html': '{% for item in seq %}[{% block item scoped %}'
+ '{{ item }}{% endblock %}]{% endfor %}'
+ }))
+ t = env.from_string('{% extends "master.html" %}{% block item %}'
+ '{{ super() }}|{{ item * 2 }}{% endblock %}')
+ assert t.render(seq=list(range(5))) == '[0|0][1|2][2|4][3|6][4|8]'
+
+ def test_scoped_block_after_inheritance(self, env):
+ env = Environment(loader=DictLoader({
+ 'layout.html': '''
+ {% block useless %}{% endblock %}
+ ''',
+ 'index.html': '''
+ {%- extends 'layout.html' %}
+ {% from 'helpers.html' import foo with context %}
+ {% block useless %}
+ {% for x in [1, 2, 3] %}
+ {% block testing scoped %}
+ {{ foo(x) }}
+ {% endblock %}
+ {% endfor %}
+ {% endblock %}
+ ''',
+ 'helpers.html': '''
+ {% macro foo(x) %}{{ the_foo + x }}{% endmacro %}
+ '''
+ }))
+ rv = env.get_template('index.html').render(the_foo=42).split()
+ assert rv == ['43', '44', '45']
+
+
+@pytest.mark.inheritance
+class TestBugFix():
+
+ def test_fixed_macro_scoping_bug(self, env):
+ assert Environment(loader=DictLoader({
+ 'test.html': '''\
+ {% extends 'details.html' %}
+
+ {% macro my_macro() %}
+ my_macro
+ {% endmacro %}
+
+ {% block inner_box %}
+ {{ my_macro() }}
+ {% endblock %}
+ ''',
+ 'details.html': '''\
+ {% extends 'standard.html' %}
+
+ {% macro my_macro() %}
+ my_macro
+ {% endmacro %}
+
+ {% block content %}
+ {% block outer_box %}
+ outer_box
+ {% block inner_box %}
+ inner_box
+ {% endblock %}
+ {% endblock %}
+ {% endblock %}
+ ''',
+ 'standard.html': '''
+ {% block content %}&nbsp;{% endblock %}
+ '''
+ })).get_template("test.html").render().split() \
+ == [u'outer_box', u'my_macro']
+
+ def test_double_extends(self, env):
+ """Ensures that a template with more than 1 {% extends ... %} usage
+ raises a ``TemplateError``.
+ """
+ try:
+ tmpl = env.get_template('doublee')
+ except Exception as e:
+ assert isinstance(e, TemplateError)
diff --git a/deps/v8_inspector/deps/jinja2/tests/test_lexnparse.py b/deps/v8_inspector/deps/jinja2/tests/test_lexnparse.py
new file mode 100644
index 0000000000..ff334bf0ca
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/tests/test_lexnparse.py
@@ -0,0 +1,609 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.lexnparse
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ All the unittests regarding lexing, parsing and syntax.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import pytest
+
+from jinja2 import Environment, Template, TemplateSyntaxError, \
+ UndefinedError, nodes
+from jinja2._compat import iteritems, text_type, PY2
+from jinja2.lexer import Token, TokenStream, TOKEN_EOF, \
+ TOKEN_BLOCK_BEGIN, TOKEN_BLOCK_END
+
+
+# how does a string look like in jinja syntax?
+if PY2:
+ def jinja_string_repr(string):
+ return repr(string)[1:]
+else:
+ jinja_string_repr = repr
+
+
+@pytest.mark.lexnparse
+@pytest.mark.tokenstream
+class TestTokenStream():
+ test_tokens = [Token(1, TOKEN_BLOCK_BEGIN, ''),
+ Token(2, TOKEN_BLOCK_END, ''),
+ ]
+
+ def test_simple(self, env):
+ ts = TokenStream(self.test_tokens, "foo", "bar")
+ assert ts.current.type is TOKEN_BLOCK_BEGIN
+ assert bool(ts)
+ assert not bool(ts.eos)
+ next(ts)
+ assert ts.current.type is TOKEN_BLOCK_END
+ assert bool(ts)
+ assert not bool(ts.eos)
+ next(ts)
+ assert ts.current.type is TOKEN_EOF
+ assert not bool(ts)
+ assert bool(ts.eos)
+
+ def test_iter(self, env):
+ token_types = [
+ t.type for t in TokenStream(self.test_tokens, "foo", "bar")
+ ]
+ assert token_types == ['block_begin', 'block_end', ]
+
+
+@pytest.mark.lexnparse
+@pytest.mark.lexer
+class TestLexer():
+
+ def test_raw1(self, env):
+ tmpl = env.from_string(
+ '{% raw %}foo{% endraw %}|'
+ '{%raw%}{{ bar }}|{% baz %}{% endraw %}')
+ assert tmpl.render() == 'foo|{{ bar }}|{% baz %}'
+
+ def test_raw2(self, env):
+ tmpl = env.from_string('1 {%- raw -%} 2 {%- endraw -%} 3')
+ assert tmpl.render() == '123'
+
+ def test_balancing(self, env):
+ env = Environment('{%', '%}', '${', '}')
+ tmpl = env.from_string('''{% for item in seq
+ %}${{'foo': item}|upper}{% endfor %}''')
+ assert tmpl.render(seq=list(range(3))) \
+ == "{'FOO': 0}{'FOO': 1}{'FOO': 2}"
+
+ def test_comments(self, env):
+ env = Environment('<!--', '-->', '{', '}')
+ tmpl = env.from_string('''\
+<ul>
+<!--- for item in seq -->
+ <li>{item}</li>
+<!--- endfor -->
+</ul>''')
+ assert tmpl.render(seq=list(range(3))) \
+ == ("<ul>\n <li>0</li>\n ""<li>1</li>\n <li>2</li>\n</ul>")
+
+ def test_string_escapes(self, env):
+ for char in u'\0', u'\u2668', u'\xe4', u'\t', u'\r', u'\n':
+ tmpl = env.from_string('{{ %s }}' % jinja_string_repr(char))
+ assert tmpl.render() == char
+ assert env.from_string('{{ "\N{HOT SPRINGS}" }}').render() == u'\u2668'
+
+ def test_bytefallback(self, env):
+ from pprint import pformat
+ tmpl = env.from_string(u'''{{ 'foo'|pprint }}|{{ 'bär'|pprint }}''')
+ assert tmpl.render() == pformat('foo') + '|' + pformat(u'bär')
+
+ def test_operators(self, env):
+ from jinja2.lexer import operators
+ for test, expect in iteritems(operators):
+ if test in '([{}])':
+ continue
+ stream = env.lexer.tokenize('{{ %s }}' % test)
+ next(stream)
+ assert stream.current.type == expect
+
+ def test_normalizing(self, env):
+ for seq in '\r', '\r\n', '\n':
+ env = Environment(newline_sequence=seq)
+ tmpl = env.from_string('1\n2\r\n3\n4\n')
+ result = tmpl.render()
+ assert result.replace(seq, 'X') == '1X2X3X4'
+
+ def test_trailing_newline(self, env):
+ for keep in [True, False]:
+ env = Environment(keep_trailing_newline=keep)
+ for template, expected in [
+ ('', {}),
+ ('no\nnewline', {}),
+ ('with\nnewline\n', {False: 'with\nnewline'}),
+ ('with\nseveral\n\n\n', {False: 'with\nseveral\n\n'}),
+ ]:
+ tmpl = env.from_string(template)
+ expect = expected.get(keep, template)
+ result = tmpl.render()
+ assert result == expect, (keep, template, result, expect)
+
+
+@pytest.mark.lexnparse
+@pytest.mark.parser
+class TestParser():
+
+ def test_php_syntax(self, env):
+ env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->')
+ tmpl = env.from_string('''\
+<!-- I'm a comment, I'm not interesting -->\
+<? for item in seq -?>
+ <?= item ?>
+<?- endfor ?>''')
+ assert tmpl.render(seq=list(range(5))) == '01234'
+
+ def test_erb_syntax(self, env):
+ env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>')
+ tmpl = env.from_string('''\
+<%# I'm a comment, I'm not interesting %>\
+<% for item in seq -%>
+ <%= item %>
+<%- endfor %>''')
+ assert tmpl.render(seq=list(range(5))) == '01234'
+
+ def test_comment_syntax(self, env):
+ env = Environment('<!--', '-->', '${', '}', '<!--#', '-->')
+ tmpl = env.from_string('''\
+<!--# I'm a comment, I'm not interesting -->\
+<!-- for item in seq --->
+ ${item}
+<!--- endfor -->''')
+ assert tmpl.render(seq=list(range(5))) == '01234'
+
+ def test_balancing(self, env):
+ tmpl = env.from_string('''{{{'foo':'bar'}.foo}}''')
+ assert tmpl.render() == 'bar'
+
+ def test_start_comment(self, env):
+ tmpl = env.from_string('''{# foo comment
+and bar comment #}
+{% macro blub() %}foo{% endmacro %}
+{{ blub() }}''')
+ assert tmpl.render().strip() == 'foo'
+
+ def test_line_syntax(self, env):
+ env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%')
+ tmpl = env.from_string('''\
+<%# regular comment %>
+% for item in seq:
+ ${item}
+% endfor''')
+ assert [
+ int(x.strip()) for x in tmpl.render(seq=list(range(5))).split()
+ ] == list(range(5))
+
+ env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##')
+ tmpl = env.from_string('''\
+<%# regular comment %>
+% for item in seq:
+ ${item} ## the rest of the stuff
+% endfor''')
+ assert [
+ int(x.strip()) for x in tmpl.render(seq=list(range(5))).split()
+ ] == list(range(5))
+
+ def test_line_syntax_priority(self, env):
+ # XXX: why is the whitespace there in front of the newline?
+ env = Environment('{%', '%}', '${', '}', '/*', '*/', '##', '#')
+ tmpl = env.from_string('''\
+/* ignore me.
+ I'm a multiline comment */
+## for item in seq:
+* ${item} # this is just extra stuff
+## endfor''')
+ assert tmpl.render(seq=[1, 2]).strip() == '* 1\n* 2'
+ env = Environment('{%', '%}', '${', '}', '/*', '*/', '#', '##')
+ tmpl = env.from_string('''\
+/* ignore me.
+ I'm a multiline comment */
+# for item in seq:
+* ${item} ## this is just extra stuff
+ ## extra stuff i just want to ignore
+# endfor''')
+ assert tmpl.render(seq=[1, 2]).strip() == '* 1\n\n* 2'
+
+ def test_error_messages(self, env):
+ def assert_error(code, expected):
+ try:
+ Template(code)
+ except TemplateSyntaxError as e:
+ assert str(e) == expected, 'unexpected error message'
+ else:
+ assert False, 'that was supposed to be an error'
+
+ assert_error('{% for item in seq %}...{% endif %}',
+ "Encountered unknown tag 'endif'. Jinja was looking "
+ "for the following tags: 'endfor' or 'else'. The "
+ "innermost block that needs to be closed is 'for'.")
+ assert_error(
+ '{% if foo %}{% for item in seq %}...{% endfor %}{% endfor %}',
+ "Encountered unknown tag 'endfor'. Jinja was looking for "
+ "the following tags: 'elif' or 'else' or 'endif'. The "
+ "innermost block that needs to be closed is 'if'.")
+ assert_error('{% if foo %}',
+ "Unexpected end of template. Jinja was looking for the "
+ "following tags: 'elif' or 'else' or 'endif'. The "
+ "innermost block that needs to be closed is 'if'.")
+ assert_error('{% for item in seq %}',
+ "Unexpected end of template. Jinja was looking for the "
+ "following tags: 'endfor' or 'else'. The innermost block "
+ "that needs to be closed is 'for'.")
+ assert_error(
+ '{% block foo-bar-baz %}',
+ "Block names in Jinja have to be valid Python identifiers "
+ "and may not contain hyphens, use an underscore instead.")
+ assert_error('{% unknown_tag %}',
+ "Encountered unknown tag 'unknown_tag'.")
+
+
+@pytest.mark.lexnparse
+@pytest.mark.syntax
+class TestSyntax():
+
+ def test_call(self, env):
+ env = Environment()
+ env.globals['foo'] = lambda a, b, c, e, g: a + b + c + e + g
+ tmpl = env.from_string(
+ "{{ foo('a', c='d', e='f', *['b'], **{'g': 'h'}) }}"
+ )
+ assert tmpl.render() == 'abdfh'
+
+ def test_slicing(self, env):
+ tmpl = env.from_string('{{ [1, 2, 3][:] }}|{{ [1, 2, 3][::-1] }}')
+ assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]'
+
+ def test_attr(self, env):
+ tmpl = env.from_string("{{ foo.bar }}|{{ foo['bar'] }}")
+ assert tmpl.render(foo={'bar': 42}) == '42|42'
+
+ def test_subscript(self, env):
+ tmpl = env.from_string("{{ foo[0] }}|{{ foo[-1] }}")
+ assert tmpl.render(foo=[0, 1, 2]) == '0|2'
+
+ def test_tuple(self, env):
+ tmpl = env.from_string('{{ () }}|{{ (1,) }}|{{ (1, 2) }}')
+ assert tmpl.render() == '()|(1,)|(1, 2)'
+
+ def test_math(self, env):
+ tmpl = env.from_string('{{ (1 + 1 * 2) - 3 / 2 }}|{{ 2**3 }}')
+ assert tmpl.render() == '1.5|8'
+
+ def test_div(self, env):
+ tmpl = env.from_string('{{ 3 // 2 }}|{{ 3 / 2 }}|{{ 3 % 2 }}')
+ assert tmpl.render() == '1|1.5|1'
+
+ def test_unary(self, env):
+ tmpl = env.from_string('{{ +3 }}|{{ -3 }}')
+ assert tmpl.render() == '3|-3'
+
+ def test_concat(self, env):
+ tmpl = env.from_string("{{ [1, 2] ~ 'foo' }}")
+ assert tmpl.render() == '[1, 2]foo'
+
+ def test_compare(self, env):
+ tmpl = env.from_string('{{ 1 > 0 }}|{{ 1 >= 1 }}|{{ 2 < 3 }}|'
+ '{{ 2 == 2 }}|{{ 1 <= 1 }}')
+ assert tmpl.render() == 'True|True|True|True|True'
+
+ def test_inop(self, env):
+ tmpl = env.from_string('{{ 1 in [1, 2, 3] }}|{{ 1 not in [1, 2, 3] }}')
+ assert tmpl.render() == 'True|False'
+
+ def test_literals(self, env):
+ tmpl = env.from_string('{{ [] }}|{{ {} }}|{{ () }}')
+ assert tmpl.render().lower() == '[]|{}|()'
+
+ def test_bool(self, env):
+ tmpl = env.from_string('{{ true and false }}|{{ false '
+ 'or true }}|{{ not false }}')
+ assert tmpl.render() == 'False|True|True'
+
+ def test_grouping(self, env):
+ tmpl = env.from_string(
+ '{{ (true and false) or (false and true) and not false }}')
+ assert tmpl.render() == 'False'
+
+ def test_django_attr(self, env):
+ tmpl = env.from_string('{{ [1, 2, 3].0 }}|{{ [[1]].0.0 }}')
+ assert tmpl.render() == '1|1'
+
+ def test_conditional_expression(self, env):
+ tmpl = env.from_string('''{{ 0 if true else 1 }}''')
+ assert tmpl.render() == '0'
+
+ def test_short_conditional_expression(self, env):
+ tmpl = env.from_string('<{{ 1 if false }}>')
+ assert tmpl.render() == '<>'
+
+ tmpl = env.from_string('<{{ (1 if false).bar }}>')
+ pytest.raises(UndefinedError, tmpl.render)
+
+ def test_filter_priority(self, env):
+ tmpl = env.from_string('{{ "foo"|upper + "bar"|upper }}')
+ assert tmpl.render() == 'FOOBAR'
+
+ def test_function_calls(self, env):
+ tests = [
+ (True, '*foo, bar'),
+ (True, '*foo, *bar'),
+ (True, '*foo, bar=42'),
+ (True, '**foo, *bar'),
+ (True, '**foo, bar'),
+ (False, 'foo, bar'),
+ (False, 'foo, bar=42'),
+ (False, 'foo, bar=23, *args'),
+ (False, 'a, b=c, *d, **e'),
+ (False, '*foo, **bar')
+ ]
+ for should_fail, sig in tests:
+ if should_fail:
+ pytest.raises(TemplateSyntaxError,
+ env.from_string, '{{ foo(%s) }}' % sig)
+ else:
+ env.from_string('foo(%s)' % sig)
+
+ def test_tuple_expr(self, env):
+ for tmpl in [
+ '{{ () }}',
+ '{{ (1, 2) }}',
+ '{{ (1, 2,) }}',
+ '{{ 1, }}',
+ '{{ 1, 2 }}',
+ '{% for foo, bar in seq %}...{% endfor %}',
+ '{% for x in foo, bar %}...{% endfor %}',
+ '{% for x in foo, %}...{% endfor %}'
+ ]:
+ assert env.from_string(tmpl)
+
+ def test_trailing_comma(self, env):
+ tmpl = env.from_string('{{ (1, 2,) }}|{{ [1, 2,] }}|{{ {1: 2,} }}')
+ assert tmpl.render().lower() == '(1, 2)|[1, 2]|{1: 2}'
+
+ def test_block_end_name(self, env):
+ env.from_string('{% block foo %}...{% endblock foo %}')
+ pytest.raises(TemplateSyntaxError, env.from_string,
+ '{% block x %}{% endblock y %}')
+
+ def test_constant_casing(self, env):
+ for const in True, False, None:
+ tmpl = env.from_string('{{ %s }}|{{ %s }}|{{ %s }}' % (
+ str(const), str(const).lower(), str(const).upper()
+ ))
+ assert tmpl.render() == '%s|%s|' % (const, const)
+
+ def test_test_chaining(self, env):
+ pytest.raises(TemplateSyntaxError, env.from_string,
+ '{{ foo is string is sequence }}')
+ assert env.from_string(
+ '{{ 42 is string or 42 is number }}'
+ ).render() == 'True'
+
+ def test_string_concatenation(self, env):
+ tmpl = env.from_string('{{ "foo" "bar" "baz" }}')
+ assert tmpl.render() == 'foobarbaz'
+
+ def test_notin(self, env):
+ bar = range(100)
+ tmpl = env.from_string('''{{ not 42 in bar }}''')
+ assert tmpl.render(bar=bar) == text_type(not 42 in bar)
+
+ def test_implicit_subscribed_tuple(self, env):
+ class Foo(object):
+ def __getitem__(self, x):
+ return x
+ t = env.from_string('{{ foo[1, 2] }}')
+ assert t.render(foo=Foo()) == u'(1, 2)'
+
+ def test_raw2(self, env):
+ tmpl = env.from_string('{% raw %}{{ FOO }} and {% BAR %}{% endraw %}')
+ assert tmpl.render() == '{{ FOO }} and {% BAR %}'
+
+ def test_const(self, env):
+ tmpl = env.from_string(
+ '{{ true }}|{{ false }}|{{ none }}|'
+ '{{ none is defined }}|{{ missing is defined }}')
+ assert tmpl.render() == 'True|False|None|True|False'
+
+ def test_neg_filter_priority(self, env):
+ node = env.parse('{{ -1|foo }}')
+ assert isinstance(node.body[0].nodes[0], nodes.Filter)
+ assert isinstance(node.body[0].nodes[0].node, nodes.Neg)
+
+ def test_const_assign(self, env):
+ constass1 = '''{% set true = 42 %}'''
+ constass2 = '''{% for none in seq %}{% endfor %}'''
+ for tmpl in constass1, constass2:
+ pytest.raises(TemplateSyntaxError, env.from_string, tmpl)
+
+ def test_localset(self, env):
+ tmpl = env.from_string('''{% set foo = 0 %}\
+{% for item in [1, 2] %}{% set foo = 1 %}{% endfor %}\
+{{ foo }}''')
+ assert tmpl.render() == '0'
+
+ def test_parse_unary(self, env):
+ tmpl = env.from_string('{{ -foo["bar"] }}')
+ assert tmpl.render(foo={'bar': 42}) == '-42'
+ tmpl = env.from_string('{{ -foo["bar"]|abs }}')
+ assert tmpl.render(foo={'bar': 42}) == '42'
+
+
+@pytest.mark.lexnparse
+@pytest.mark.lstripblocks
+class TestLstripBlocks():
+
+ def test_lstrip(self, env):
+ env = Environment(lstrip_blocks=True, trim_blocks=False)
+ tmpl = env.from_string(''' {% if True %}\n {% endif %}''')
+ assert tmpl.render() == "\n"
+
+ def test_lstrip_trim(self, env):
+ env = Environment(lstrip_blocks=True, trim_blocks=True)
+ tmpl = env.from_string(''' {% if True %}\n {% endif %}''')
+ assert tmpl.render() == ""
+
+ def test_no_lstrip(self, env):
+ env = Environment(lstrip_blocks=True, trim_blocks=False)
+ tmpl = env.from_string(''' {%+ if True %}\n {%+ endif %}''')
+ assert tmpl.render() == " \n "
+
+ def test_lstrip_endline(self, env):
+ env = Environment(lstrip_blocks=True, trim_blocks=False)
+ tmpl = env.from_string(
+ ''' hello{% if True %}\n goodbye{% endif %}''')
+ assert tmpl.render() == " hello\n goodbye"
+
+ def test_lstrip_inline(self, env):
+ env = Environment(lstrip_blocks=True, trim_blocks=False)
+ tmpl = env.from_string(''' {% if True %}hello {% endif %}''')
+ assert tmpl.render() == 'hello '
+
+ def test_lstrip_nested(self, env):
+ env = Environment(lstrip_blocks=True, trim_blocks=False)
+ tmpl = env.from_string(
+ ''' {% if True %}a {% if True %}b {% endif %}c {% endif %}''')
+ assert tmpl.render() == 'a b c '
+
+ def test_lstrip_left_chars(self, env):
+ env = Environment(lstrip_blocks=True, trim_blocks=False)
+ tmpl = env.from_string(''' abc {% if True %}
+ hello{% endif %}''')
+ assert tmpl.render() == ' abc \n hello'
+
+ def test_lstrip_embeded_strings(self, env):
+ env = Environment(lstrip_blocks=True, trim_blocks=False)
+ tmpl = env.from_string(''' {% set x = " {% str %} " %}{{ x }}''')
+ assert tmpl.render() == ' {% str %} '
+
+ def test_lstrip_preserve_leading_newlines(self, env):
+ env = Environment(lstrip_blocks=True, trim_blocks=False)
+ tmpl = env.from_string('''\n\n\n{% set hello = 1 %}''')
+ assert tmpl.render() == '\n\n\n'
+
+ def test_lstrip_comment(self, env):
+ env = Environment(lstrip_blocks=True, trim_blocks=False)
+ tmpl = env.from_string(''' {# if True #}
+hello
+ {#endif#}''')
+ assert tmpl.render() == '\nhello\n'
+
+ def test_lstrip_angle_bracket_simple(self, env):
+ env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##',
+ lstrip_blocks=True, trim_blocks=True)
+ tmpl = env.from_string(''' <% if True %>hello <% endif %>''')
+ assert tmpl.render() == 'hello '
+
+ def test_lstrip_angle_bracket_comment(self, env):
+ env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##',
+ lstrip_blocks=True, trim_blocks=True)
+ tmpl = env.from_string(''' <%# if True %>hello <%# endif %>''')
+ assert tmpl.render() == 'hello '
+
+ def test_lstrip_angle_bracket(self, env):
+ env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##',
+ lstrip_blocks=True, trim_blocks=True)
+ tmpl = env.from_string('''\
+ <%# regular comment %>
+ <% for item in seq %>
+${item} ## the rest of the stuff
+ <% endfor %>''')
+ assert tmpl.render(seq=range(5)) == \
+ ''.join('%s\n' % x for x in range(5))
+
+ def test_lstrip_angle_bracket_compact(self, env):
+ env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##',
+ lstrip_blocks=True, trim_blocks=True)
+ tmpl = env.from_string('''\
+ <%#regular comment%>
+ <%for item in seq%>
+${item} ## the rest of the stuff
+ <%endfor%>''')
+ assert tmpl.render(seq=range(5)) == \
+ ''.join('%s\n' % x for x in range(5))
+
+ def test_php_syntax_with_manual(self, env):
+ env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->',
+ lstrip_blocks=True, trim_blocks=True)
+ tmpl = env.from_string('''\
+ <!-- I'm a comment, I'm not interesting -->
+ <? for item in seq -?>
+ <?= item ?>
+ <?- endfor ?>''')
+ assert tmpl.render(seq=range(5)) == '01234'
+
+ def test_php_syntax(self, env):
+ env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->',
+ lstrip_blocks=True, trim_blocks=True)
+ tmpl = env.from_string('''\
+ <!-- I'm a comment, I'm not interesting -->
+ <? for item in seq ?>
+ <?= item ?>
+ <? endfor ?>''')
+ assert tmpl.render(seq=range(5)) \
+ == ''.join(' %s\n' % x for x in range(5))
+
+ def test_php_syntax_compact(self, env):
+ env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->',
+ lstrip_blocks=True, trim_blocks=True)
+ tmpl = env.from_string('''\
+ <!-- I'm a comment, I'm not interesting -->
+ <?for item in seq?>
+ <?=item?>
+ <?endfor?>''')
+ assert tmpl.render(seq=range(5)) \
+ == ''.join(' %s\n' % x for x in range(5))
+
+ def test_erb_syntax(self, env):
+ env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>',
+ lstrip_blocks=True, trim_blocks=True)
+ # env.from_string('')
+ # for n,r in env.lexer.rules.iteritems():
+ # print n
+ # print env.lexer.rules['root'][0][0].pattern
+ # print "'%s'" % tmpl.render(seq=range(5))
+ tmpl = env.from_string('''\
+<%# I'm a comment, I'm not interesting %>
+ <% for item in seq %>
+ <%= item %>
+ <% endfor %>
+''')
+ assert tmpl.render(seq=range(5)) \
+ == ''.join(' %s\n' % x for x in range(5))
+
+ def test_erb_syntax_with_manual(self, env):
+ env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>',
+ lstrip_blocks=True, trim_blocks=True)
+ tmpl = env.from_string('''\
+<%# I'm a comment, I'm not interesting %>
+ <% for item in seq -%>
+ <%= item %>
+ <%- endfor %>''')
+ assert tmpl.render(seq=range(5)) == '01234'
+
+ def test_erb_syntax_no_lstrip(self, env):
+ env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>',
+ lstrip_blocks=True, trim_blocks=True)
+ tmpl = env.from_string('''\
+<%# I'm a comment, I'm not interesting %>
+ <%+ for item in seq -%>
+ <%= item %>
+ <%- endfor %>''')
+ assert tmpl.render(seq=range(5)) == ' 01234'
+
+ def test_comment_syntax(self, env):
+ env = Environment('<!--', '-->', '${', '}', '<!--#', '-->',
+ lstrip_blocks=True, trim_blocks=True)
+ tmpl = env.from_string('''\
+<!--# I'm a comment, I'm not interesting -->\
+<!-- for item in seq --->
+ ${item}
+<!--- endfor -->''')
+ assert tmpl.render(seq=range(5)) == '01234'
diff --git a/deps/v8_inspector/deps/jinja2/tests/test_loader.py b/deps/v8_inspector/deps/jinja2/tests/test_loader.py
new file mode 100644
index 0000000000..6d22fad390
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/tests/test_loader.py
@@ -0,0 +1,220 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.loader
+ ~~~~~~~~~~~~~~~~~~~~~~~
+
+ Test the loaders.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import os
+import sys
+import tempfile
+import shutil
+import pytest
+
+from jinja2 import Environment, loaders
+from jinja2._compat import PYPY, PY2
+from jinja2.loaders import split_template_path
+from jinja2.exceptions import TemplateNotFound
+
+
+@pytest.mark.loaders
+class TestLoaders():
+
+ def test_dict_loader(self, dict_loader):
+ env = Environment(loader=dict_loader)
+ tmpl = env.get_template('justdict.html')
+ assert tmpl.render().strip() == 'FOO'
+ pytest.raises(TemplateNotFound, env.get_template, 'missing.html')
+
+ def test_package_loader(self, package_loader):
+ env = Environment(loader=package_loader)
+ tmpl = env.get_template('test.html')
+ assert tmpl.render().strip() == 'BAR'
+ pytest.raises(TemplateNotFound, env.get_template, 'missing.html')
+
+ def test_filesystem_loader(self, filesystem_loader):
+ env = Environment(loader=filesystem_loader)
+ tmpl = env.get_template('test.html')
+ assert tmpl.render().strip() == 'BAR'
+ tmpl = env.get_template('foo/test.html')
+ assert tmpl.render().strip() == 'FOO'
+ pytest.raises(TemplateNotFound, env.get_template, 'missing.html')
+
+ def test_choice_loader(self, choice_loader):
+ env = Environment(loader=choice_loader)
+ tmpl = env.get_template('justdict.html')
+ assert tmpl.render().strip() == 'FOO'
+ tmpl = env.get_template('test.html')
+ assert tmpl.render().strip() == 'BAR'
+ pytest.raises(TemplateNotFound, env.get_template, 'missing.html')
+
+ def test_function_loader(self, function_loader):
+ env = Environment(loader=function_loader)
+ tmpl = env.get_template('justfunction.html')
+ assert tmpl.render().strip() == 'FOO'
+ pytest.raises(TemplateNotFound, env.get_template, 'missing.html')
+
+ def test_prefix_loader(self, prefix_loader):
+ env = Environment(loader=prefix_loader)
+ tmpl = env.get_template('a/test.html')
+ assert tmpl.render().strip() == 'BAR'
+ tmpl = env.get_template('b/justdict.html')
+ assert tmpl.render().strip() == 'FOO'
+ pytest.raises(TemplateNotFound, env.get_template, 'missing')
+
+ def test_caching(self):
+ changed = False
+
+ class TestLoader(loaders.BaseLoader):
+ def get_source(self, environment, template):
+ return u'foo', None, lambda: not changed
+ env = Environment(loader=TestLoader(), cache_size=-1)
+ tmpl = env.get_template('template')
+ assert tmpl is env.get_template('template')
+ changed = True
+ assert tmpl is not env.get_template('template')
+ changed = False
+
+ env = Environment(loader=TestLoader(), cache_size=0)
+ assert env.get_template('template') \
+ is not env.get_template('template')
+
+ env = Environment(loader=TestLoader(), cache_size=2)
+ t1 = env.get_template('one')
+ t2 = env.get_template('two')
+ assert t2 is env.get_template('two')
+ assert t1 is env.get_template('one')
+ t3 = env.get_template('three')
+ assert 'one' in env.cache
+ assert 'two' not in env.cache
+ assert 'three' in env.cache
+
+ def test_dict_loader_cache_invalidates(self):
+ mapping = {'foo': "one"}
+ env = Environment(loader=loaders.DictLoader(mapping))
+ assert env.get_template('foo').render() == "one"
+ mapping['foo'] = "two"
+ assert env.get_template('foo').render() == "two"
+
+ def test_split_template_path(self):
+ assert split_template_path('foo/bar') == ['foo', 'bar']
+ assert split_template_path('./foo/bar') == ['foo', 'bar']
+ pytest.raises(TemplateNotFound, split_template_path, '../foo')
+
+
+@pytest.mark.loaders
+@pytest.mark.moduleloader
+class TestModuleLoader():
+ archive = None
+
+ def compile_down(self, prefix_loader, zip='deflated', py_compile=False):
+ log = []
+ self.reg_env = Environment(loader=prefix_loader)
+ if zip is not None:
+ fd, self.archive = tempfile.mkstemp(suffix='.zip')
+ os.close(fd)
+ else:
+ self.archive = tempfile.mkdtemp()
+ self.reg_env.compile_templates(self.archive, zip=zip,
+ log_function=log.append,
+ py_compile=py_compile)
+ self.mod_env = Environment(loader=loaders.ModuleLoader(self.archive))
+ return ''.join(log)
+
+ def teardown(self):
+ if hasattr(self, 'mod_env'):
+ if os.path.isfile(self.archive):
+ os.remove(self.archive)
+ else:
+ shutil.rmtree(self.archive)
+ self.archive = None
+
+ def test_log(self, prefix_loader):
+ log = self.compile_down(prefix_loader)
+ assert 'Compiled "a/foo/test.html" as ' \
+ 'tmpl_a790caf9d669e39ea4d280d597ec891c4ef0404a' in log
+ assert 'Finished compiling templates' in log
+ assert 'Could not compile "a/syntaxerror.html": ' \
+ 'Encountered unknown tag \'endif\'' in log
+
+ def _test_common(self):
+ tmpl1 = self.reg_env.get_template('a/test.html')
+ tmpl2 = self.mod_env.get_template('a/test.html')
+ assert tmpl1.render() == tmpl2.render()
+
+ tmpl1 = self.reg_env.get_template('b/justdict.html')
+ tmpl2 = self.mod_env.get_template('b/justdict.html')
+ assert tmpl1.render() == tmpl2.render()
+
+ def test_deflated_zip_compile(self, prefix_loader):
+ self.compile_down(prefix_loader, zip='deflated')
+ self._test_common()
+
+ def test_stored_zip_compile(self, prefix_loader):
+ self.compile_down(prefix_loader, zip='stored')
+ self._test_common()
+
+ def test_filesystem_compile(self, prefix_loader):
+ self.compile_down(prefix_loader, zip=None)
+ self._test_common()
+
+ def test_weak_references(self, prefix_loader):
+ self.compile_down(prefix_loader)
+ tmpl = self.mod_env.get_template('a/test.html')
+ key = loaders.ModuleLoader.get_template_key('a/test.html')
+ name = self.mod_env.loader.module.__name__
+
+ assert hasattr(self.mod_env.loader.module, key)
+ assert name in sys.modules
+
+ # unset all, ensure the module is gone from sys.modules
+ self.mod_env = tmpl = None
+
+ try:
+ import gc
+ gc.collect()
+ except:
+ pass
+
+ assert name not in sys.modules
+
+ # This test only makes sense on non-pypy python 2
+ @pytest.mark.skipif(
+ not (PY2 and not PYPY),
+ reason='This test only makes sense on non-pypy python 2')
+ def test_byte_compilation(self, prefix_loader):
+ log = self.compile_down(prefix_loader, py_compile=True)
+ assert 'Byte-compiled "a/test.html"' in log
+ tmpl1 = self.mod_env.get_template('a/test.html')
+ mod = self.mod_env.loader.module. \
+ tmpl_3c4ddf650c1a73df961a6d3d2ce2752f1b8fd490
+ assert mod.__file__.endswith('.pyc')
+
+ def test_choice_loader(self, prefix_loader):
+ log = self.compile_down(prefix_loader)
+
+ self.mod_env.loader = loaders.ChoiceLoader([
+ self.mod_env.loader,
+ loaders.DictLoader({'DICT_SOURCE': 'DICT_TEMPLATE'})
+ ])
+
+ tmpl1 = self.mod_env.get_template('a/test.html')
+ assert tmpl1.render() == 'BAR'
+ tmpl2 = self.mod_env.get_template('DICT_SOURCE')
+ assert tmpl2.render() == 'DICT_TEMPLATE'
+
+ def test_prefix_loader(self, prefix_loader):
+ log = self.compile_down(prefix_loader)
+
+ self.mod_env.loader = loaders.PrefixLoader({
+ 'MOD': self.mod_env.loader,
+ 'DICT': loaders.DictLoader({'test.html': 'DICT_TEMPLATE'})
+ })
+
+ tmpl1 = self.mod_env.get_template('MOD/a/test.html')
+ assert tmpl1.render() == 'BAR'
+ tmpl2 = self.mod_env.get_template('DICT/test.html')
+ assert tmpl2.render() == 'DICT_TEMPLATE'
diff --git a/deps/v8_inspector/deps/jinja2/tests/test_regression.py b/deps/v8_inspector/deps/jinja2/tests/test_regression.py
new file mode 100644
index 0000000000..a4aa157110
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/tests/test_regression.py
@@ -0,0 +1,278 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.regression
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Tests corner cases and bugs.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import pytest
+
+from jinja2 import Template, Environment, DictLoader, TemplateSyntaxError, \
+ TemplateNotFound, PrefixLoader
+from jinja2._compat import text_type
+
+
+@pytest.mark.regression
+class TestCorner():
+
+ def test_assigned_scoping(self, env):
+ t = env.from_string('''
+ {%- for item in (1, 2, 3, 4) -%}
+ [{{ item }}]
+ {%- endfor %}
+ {{- item -}}
+ ''')
+ assert t.render(item=42) == '[1][2][3][4]42'
+
+ t = env.from_string('''
+ {%- for item in (1, 2, 3, 4) -%}
+ [{{ item }}]
+ {%- endfor %}
+ {%- set item = 42 %}
+ {{- item -}}
+ ''')
+ assert t.render() == '[1][2][3][4]42'
+
+ t = env.from_string('''
+ {%- set item = 42 %}
+ {%- for item in (1, 2, 3, 4) -%}
+ [{{ item }}]
+ {%- endfor %}
+ {{- item -}}
+ ''')
+ assert t.render() == '[1][2][3][4]42'
+
+ def test_closure_scoping(self, env):
+ t = env.from_string('''
+ {%- set wrapper = "<FOO>" %}
+ {%- for item in (1, 2, 3, 4) %}
+ {%- macro wrapper() %}[{{ item }}]{% endmacro %}
+ {{- wrapper() }}
+ {%- endfor %}
+ {{- wrapper -}}
+ ''')
+ assert t.render() == '[1][2][3][4]<FOO>'
+
+ t = env.from_string('''
+ {%- for item in (1, 2, 3, 4) %}
+ {%- macro wrapper() %}[{{ item }}]{% endmacro %}
+ {{- wrapper() }}
+ {%- endfor %}
+ {%- set wrapper = "<FOO>" %}
+ {{- wrapper -}}
+ ''')
+ assert t.render() == '[1][2][3][4]<FOO>'
+
+ t = env.from_string('''
+ {%- for item in (1, 2, 3, 4) %}
+ {%- macro wrapper() %}[{{ item }}]{% endmacro %}
+ {{- wrapper() }}
+ {%- endfor %}
+ {{- wrapper -}}
+ ''')
+ assert t.render(wrapper=23) == '[1][2][3][4]23'
+
+
+@pytest.mark.regression
+class TestBug():
+
+ def test_keyword_folding(self, env):
+ env = Environment()
+ env.filters['testing'] = lambda value, some: value + some
+ assert env.from_string("{{ 'test'|testing(some='stuff') }}") \
+ .render() == 'teststuff'
+
+ def test_extends_output_bugs(self, env):
+ env = Environment(loader=DictLoader({
+ 'parent.html': '(({% block title %}{% endblock %}))'
+ }))
+
+ t = env.from_string(
+ '{% if expr %}{% extends "parent.html" %}{% endif %}'
+ '[[{% block title %}title{% endblock %}]]'
+ '{% for item in [1, 2, 3] %}({{ item }}){% endfor %}'
+ )
+ assert t.render(expr=False) == '[[title]](1)(2)(3)'
+ assert t.render(expr=True) == '((title))'
+
+ def test_urlize_filter_escaping(self, env):
+ tmpl = env.from_string('{{ "http://www.example.org/<foo"|urlize }}')
+ assert tmpl.render() == '<a href="http://www.example.org/&lt;foo">'\
+ 'http://www.example.org/&lt;foo</a>'
+
+ def test_loop_call_loop(self, env):
+ tmpl = env.from_string('''
+
+ {% macro test() %}
+ {{ caller() }}
+ {% endmacro %}
+
+ {% for num1 in range(5) %}
+ {% call test() %}
+ {% for num2 in range(10) %}
+ {{ loop.index }}
+ {% endfor %}
+ {% endcall %}
+ {% endfor %}
+
+ ''')
+
+ assert tmpl.render().split() \
+ == [text_type(x) for x in range(1, 11)] * 5
+
+ def test_weird_inline_comment(self, env):
+ env = Environment(line_statement_prefix='%')
+ pytest.raises(TemplateSyntaxError, env.from_string,
+ '% for item in seq {# missing #}\n...% endfor')
+
+ def test_old_macro_loop_scoping_bug(self, env):
+ tmpl = env.from_string('{% for i in (1, 2) %}{{ i }}{% endfor %}'
+ '{% macro i() %}3{% endmacro %}{{ i() }}')
+ assert tmpl.render() == '123'
+
+ def test_partial_conditional_assignments(self, env):
+ tmpl = env.from_string('{% if b %}{% set a = 42 %}{% endif %}{{ a }}')
+ assert tmpl.render(a=23) == '23'
+ assert tmpl.render(b=True) == '42'
+
+ def test_stacked_locals_scoping_bug(self, env):
+ env = Environment(line_statement_prefix='#')
+ t = env.from_string('''\
+# for j in [1, 2]:
+# set x = 1
+# for i in [1, 2]:
+# print x
+# if i % 2 == 0:
+# set x = x + 1
+# endif
+# endfor
+# endfor
+# if a
+# print 'A'
+# elif b
+# print 'B'
+# elif c == d
+# print 'C'
+# else
+# print 'D'
+# endif
+ ''')
+ assert t.render(a=0, b=False, c=42, d=42.0) == '1111C'
+
+ def test_stacked_locals_scoping_bug_twoframe(self, env):
+ t = Template('''
+ {% set x = 1 %}
+ {% for item in foo %}
+ {% if item == 1 %}
+ {% set x = 2 %}
+ {% endif %}
+ {% endfor %}
+ {{ x }}
+ ''')
+ rv = t.render(foo=[1]).strip()
+ assert rv == u'1'
+
+ def test_call_with_args(self, env):
+ t = Template("""{% macro dump_users(users) -%}
+ <ul>
+ {%- for user in users -%}
+ <li><p>{{ user.username|e }}</p>{{ caller(user) }}</li>
+ {%- endfor -%}
+ </ul>
+ {%- endmacro -%}
+
+ {% call(user) dump_users(list_of_user) -%}
+ <dl>
+ <dl>Realname</dl>
+ <dd>{{ user.realname|e }}</dd>
+ <dl>Description</dl>
+ <dd>{{ user.description }}</dd>
+ </dl>
+ {% endcall %}""")
+
+ assert [x.strip() for x in t.render(list_of_user=[{
+ 'username': 'apo',
+ 'realname': 'something else',
+ 'description': 'test'
+ }]).splitlines()] == [
+ u'<ul><li><p>apo</p><dl>',
+ u'<dl>Realname</dl>',
+ u'<dd>something else</dd>',
+ u'<dl>Description</dl>',
+ u'<dd>test</dd>',
+ u'</dl>',
+ u'</li></ul>'
+ ]
+
+ def test_empty_if_condition_fails(self, env):
+ pytest.raises(TemplateSyntaxError,
+ Template, '{% if %}....{% endif %}')
+ pytest.raises(TemplateSyntaxError,
+ Template, '{% if foo %}...{% elif %}...{% endif %}')
+ pytest.raises(TemplateSyntaxError,
+ Template, '{% for x in %}..{% endfor %}')
+
+ def test_recursive_loop_bug(self, env):
+ tpl1 = Template("""
+ {% for p in foo recursive%}
+ {{p.bar}}
+ {% for f in p.fields recursive%}
+ {{f.baz}}
+ {{p.bar}}
+ {% if f.rec %}
+ {{ loop(f.sub) }}
+ {% endif %}
+ {% endfor %}
+ {% endfor %}
+ """)
+
+ tpl2 = Template("""
+ {% for p in foo%}
+ {{p.bar}}
+ {% for f in p.fields recursive%}
+ {{f.baz}}
+ {{p.bar}}
+ {% if f.rec %}
+ {{ loop(f.sub) }}
+ {% endif %}
+ {% endfor %}
+ {% endfor %}
+ """)
+
+ def test_else_loop_bug(self, env):
+ t = Template('''
+ {% for x in y %}
+ {{ loop.index0 }}
+ {% else %}
+ {% for i in range(3) %}{{ i }}{% endfor %}
+ {% endfor %}
+ ''')
+ assert t.render(y=[]).strip() == '012'
+
+ def test_correct_prefix_loader_name(self, env):
+ env = Environment(loader=PrefixLoader({
+ 'foo': DictLoader({})
+ }))
+ try:
+ env.get_template('foo/bar.html')
+ except TemplateNotFound as e:
+ assert e.name == 'foo/bar.html'
+ else:
+ assert False, 'expected error here'
+
+ def test_contextfunction_callable_classes(self, env):
+ from jinja2.utils import contextfunction
+
+ class CallableClass(object):
+ @contextfunction
+ def __call__(self, ctx):
+ return ctx.resolve('hello')
+
+ tpl = Template("""{{ callableclass() }}""")
+ output = tpl.render(callableclass=CallableClass(), hello='TEST')
+ expected = 'TEST'
+
+ assert output == expected
diff --git a/deps/v8_inspector/deps/jinja2/tests/test_security.py b/deps/v8_inspector/deps/jinja2/tests/test_security.py
new file mode 100644
index 0000000000..e5b463fc98
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/tests/test_security.py
@@ -0,0 +1,161 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.security
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Checks the sandbox and other security features.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import pytest
+
+from jinja2 import Environment
+from jinja2.sandbox import SandboxedEnvironment, \
+ ImmutableSandboxedEnvironment, unsafe
+from jinja2 import Markup, escape
+from jinja2.exceptions import SecurityError, TemplateSyntaxError, \
+ TemplateRuntimeError
+from jinja2._compat import text_type
+
+
+class PrivateStuff(object):
+
+ def bar(self):
+ return 23
+
+ @unsafe
+ def foo(self):
+ return 42
+
+ def __repr__(self):
+ return 'PrivateStuff'
+
+
+class PublicStuff(object):
+ bar = lambda self: 23
+ _foo = lambda self: 42
+
+ def __repr__(self):
+ return 'PublicStuff'
+
+
+@pytest.mark.sandbox
+class TestSandbox():
+
+ def test_unsafe(self, env):
+ env = SandboxedEnvironment()
+ pytest.raises(SecurityError, env.from_string("{{ foo.foo() }}").render,
+ foo=PrivateStuff())
+ assert env.from_string("{{ foo.bar() }}").render(foo=PrivateStuff()) == '23'
+
+ pytest.raises(SecurityError,
+ env.from_string("{{ foo._foo() }}").render,
+ foo=PublicStuff())
+ assert env.from_string("{{ foo.bar() }}").render(foo=PublicStuff()) == '23'
+ assert env.from_string("{{ foo.__class__ }}").render(foo=42) == ''
+ assert env.from_string("{{ foo.func_code }}").render(foo=lambda:None) == ''
+ # security error comes from __class__ already.
+ pytest.raises(SecurityError, env.from_string(
+ "{{ foo.__class__.__subclasses__() }}").render, foo=42)
+
+ def test_immutable_environment(self, env):
+ env = ImmutableSandboxedEnvironment()
+ pytest.raises(SecurityError, env.from_string(
+ '{{ [].append(23) }}').render)
+ pytest.raises(SecurityError, env.from_string(
+ '{{ {1:2}.clear() }}').render)
+
+ def test_restricted(self, env):
+ env = SandboxedEnvironment()
+ pytest.raises(TemplateSyntaxError, env.from_string,
+ "{% for item.attribute in seq %}...{% endfor %}")
+ pytest.raises(TemplateSyntaxError, env.from_string,
+ "{% for foo, bar.baz in seq %}...{% endfor %}")
+
+ def test_markup_operations(self, env):
+ # adding two strings should escape the unsafe one
+ unsafe = '<script type="application/x-some-script">alert("foo");</script>'
+ safe = Markup('<em>username</em>')
+ assert unsafe + safe == text_type(escape(unsafe)) + text_type(safe)
+
+ # string interpolations are safe to use too
+ assert Markup('<em>%s</em>') % '<bad user>' == \
+ '<em>&lt;bad user&gt;</em>'
+ assert Markup('<em>%(username)s</em>') % {
+ 'username': '<bad user>'
+ } == '<em>&lt;bad user&gt;</em>'
+
+ # an escaped object is markup too
+ assert type(Markup('foo') + 'bar') is Markup
+
+ # and it implements __html__ by returning itself
+ x = Markup("foo")
+ assert x.__html__() is x
+
+ # it also knows how to treat __html__ objects
+ class Foo(object):
+ def __html__(self):
+ return '<em>awesome</em>'
+
+ def __unicode__(self):
+ return 'awesome'
+ assert Markup(Foo()) == '<em>awesome</em>'
+ assert Markup('<strong>%s</strong>') % Foo() == \
+ '<strong><em>awesome</em></strong>'
+
+ # escaping and unescaping
+ assert escape('"<>&\'') == '&#34;&lt;&gt;&amp;&#39;'
+ assert Markup("<em>Foo &amp; Bar</em>").striptags() == "Foo & Bar"
+ assert Markup("&lt;test&gt;").unescape() == "<test>"
+
+ def test_template_data(self, env):
+ env = Environment(autoescape=True)
+ t = env.from_string('{% macro say_hello(name) %}'
+ '<p>Hello {{ name }}!</p>{% endmacro %}'
+ '{{ say_hello("<blink>foo</blink>") }}')
+ escaped_out = '<p>Hello &lt;blink&gt;foo&lt;/blink&gt;!</p>'
+ assert t.render() == escaped_out
+ assert text_type(t.module) == escaped_out
+ assert escape(t.module) == escaped_out
+ assert t.module.say_hello('<blink>foo</blink>') == escaped_out
+ assert escape(t.module.say_hello('<blink>foo</blink>')) == escaped_out
+
+ def test_attr_filter(self, env):
+ env = SandboxedEnvironment()
+ tmpl = env.from_string('{{ cls|attr("__subclasses__")() }}')
+ pytest.raises(SecurityError, tmpl.render, cls=int)
+
+ def test_binary_operator_intercepting(self, env):
+ def disable_op(left, right):
+ raise TemplateRuntimeError('that operator so does not work')
+ for expr, ctx, rv in ('1 + 2', {}, '3'), ('a + 2', {'a': 2}, '4'):
+ env = SandboxedEnvironment()
+ env.binop_table['+'] = disable_op
+ t = env.from_string('{{ %s }}' % expr)
+ assert t.render(ctx) == rv
+ env.intercepted_binops = frozenset(['+'])
+ t = env.from_string('{{ %s }}' % expr)
+ try:
+ t.render(ctx)
+ except TemplateRuntimeError as e:
+ pass
+ else:
+ assert False, 'expected runtime error'
+
+ def test_unary_operator_intercepting(self, env):
+ def disable_op(arg):
+ raise TemplateRuntimeError('that operator so does not work')
+ for expr, ctx, rv in ('-1', {}, '-1'), ('-a', {'a': 2}, '-2'):
+ env = SandboxedEnvironment()
+ env.unop_table['-'] = disable_op
+ t = env.from_string('{{ %s }}' % expr)
+ assert t.render(ctx) == rv
+ env.intercepted_unops = frozenset(['-'])
+ t = env.from_string('{{ %s }}' % expr)
+ try:
+ t.render(ctx)
+ except TemplateRuntimeError as e:
+ pass
+ else:
+ assert False, 'expected runtime error'
diff --git a/deps/v8_inspector/deps/jinja2/tests/test_tests.py b/deps/v8_inspector/deps/jinja2/tests/test_tests.py
new file mode 100644
index 0000000000..9e54038c9a
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/tests/test_tests.py
@@ -0,0 +1,104 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.tests
+ ~~~~~~~~~~~~~~~~~~~~~~
+
+ Who tests the tests?
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import pytest
+
+from jinja2 import Markup, Environment
+
+
+@pytest.mark.test_tests
+class TestTestsCase():
+
+ def test_defined(self, env):
+ tmpl = env.from_string('{{ missing is defined }}|'
+ '{{ true is defined }}')
+ assert tmpl.render() == 'False|True'
+
+ def test_even(self, env):
+ tmpl = env.from_string('''{{ 1 is even }}|{{ 2 is even }}''')
+ assert tmpl.render() == 'False|True'
+
+ def test_odd(self, env):
+ tmpl = env.from_string('''{{ 1 is odd }}|{{ 2 is odd }}''')
+ assert tmpl.render() == 'True|False'
+
+ def test_lower(self, env):
+ tmpl = env.from_string('''{{ "foo" is lower }}|{{ "FOO" is lower }}''')
+ assert tmpl.render() == 'True|False'
+
+ def test_typechecks(self, env):
+ tmpl = env.from_string('''
+ {{ 42 is undefined }}
+ {{ 42 is defined }}
+ {{ 42 is none }}
+ {{ none is none }}
+ {{ 42 is number }}
+ {{ 42 is string }}
+ {{ "foo" is string }}
+ {{ "foo" is sequence }}
+ {{ [1] is sequence }}
+ {{ range is callable }}
+ {{ 42 is callable }}
+ {{ range(5) is iterable }}
+ {{ {} is mapping }}
+ {{ mydict is mapping }}
+ {{ [] is mapping }}
+ {{ 10 is number }}
+ {{ (10 ** 100) is number }}
+ {{ 3.14159 is number }}
+ {{ complex is number }}
+ ''')
+
+ class MyDict(dict):
+ pass
+
+ assert tmpl.render(mydict=MyDict(), complex=complex(1, 2)).split() == [
+ 'False', 'True', 'False', 'True', 'True', 'False',
+ 'True', 'True', 'True', 'True', 'False', 'True',
+ 'True', 'True', 'False', 'True', 'True', 'True', 'True'
+ ]
+
+ def test_sequence(self, env):
+ tmpl = env.from_string(
+ '{{ [1, 2, 3] is sequence }}|'
+ '{{ "foo" is sequence }}|'
+ '{{ 42 is sequence }}'
+ )
+ assert tmpl.render() == 'True|True|False'
+
+ def test_upper(self, env):
+ tmpl = env.from_string('{{ "FOO" is upper }}|{{ "foo" is upper }}')
+ assert tmpl.render() == 'True|False'
+
+ def test_equalto(self, env):
+ tmpl = env.from_string('{{ foo is equalto 12 }}|'
+ '{{ foo is equalto 0 }}|'
+ '{{ foo is equalto (3 * 4) }}|'
+ '{{ bar is equalto "baz" }}|'
+ '{{ bar is equalto "zab" }}|'
+ '{{ bar is equalto ("ba" + "z") }}|'
+ '{{ bar is equalto bar }}|'
+ '{{ bar is equalto foo }}')
+ assert tmpl.render(foo=12, bar="baz") \
+ == 'True|False|True|True|False|True|True|False'
+
+ def test_sameas(self, env):
+ tmpl = env.from_string('{{ foo is sameas false }}|'
+ '{{ 0 is sameas false }}')
+ assert tmpl.render(foo=False) == 'True|False'
+
+ def test_no_paren_for_arg1(self, env):
+ tmpl = env.from_string('{{ foo is sameas none }}')
+ assert tmpl.render(foo=None) == 'True'
+
+ def test_escaped(self, env):
+ env = Environment(autoescape=True)
+ tmpl = env.from_string('{{ x is escaped }}|{{ y is escaped }}')
+ assert tmpl.render(x='foo', y=Markup('foo')) == 'False|True'
diff --git a/deps/v8_inspector/deps/jinja2/tests/test_utils.py b/deps/v8_inspector/deps/jinja2/tests/test_utils.py
new file mode 100644
index 0000000000..373103618d
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/tests/test_utils.py
@@ -0,0 +1,76 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.utils
+ ~~~~~~~~~~~~~~~~~~~~~~
+
+ Tests utilities jinja uses.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import gc
+
+import pytest
+
+import pickle
+
+from jinja2.utils import LRUCache, escape, object_type_repr
+
+
+@pytest.mark.utils
+@pytest.mark.lrucache
+class TestLRUCache():
+
+ def test_simple(self):
+ d = LRUCache(3)
+ d["a"] = 1
+ d["b"] = 2
+ d["c"] = 3
+ d["a"]
+ d["d"] = 4
+ assert len(d) == 3
+ assert 'a' in d and 'c' in d and 'd' in d and 'b' not in d
+
+ def test_pickleable(self):
+ cache = LRUCache(2)
+ cache["foo"] = 42
+ cache["bar"] = 23
+ cache["foo"]
+
+ for protocol in range(3):
+ copy = pickle.loads(pickle.dumps(cache, protocol))
+ assert copy.capacity == cache.capacity
+ assert copy._mapping == cache._mapping
+ assert copy._queue == cache._queue
+
+
+@pytest.mark.utils
+@pytest.mark.helpers
+class TestHelpers():
+
+ def test_object_type_repr(self):
+ class X(object):
+ pass
+ assert object_type_repr(42) == 'int object'
+ assert object_type_repr([]) == 'list object'
+ assert object_type_repr(X()) == 'test_utils.X object'
+ assert object_type_repr(None) == 'None'
+ assert object_type_repr(Ellipsis) == 'Ellipsis'
+
+
+@pytest.mark.utils
+@pytest.mark.markupleak
+@pytest.mark.skipif(hasattr(escape, 'func_code'),
+ reason='this test only tests the c extension')
+class TestMarkupLeak():
+
+ def test_markup_leaks(self):
+ counts = set()
+ for count in range(20):
+ for item in range(1000):
+ escape("foo")
+ escape("<foo>")
+ escape(u"foo")
+ escape(u"<foo>")
+ counts.add(len(gc.get_objects()))
+ assert len(counts) == 1, 'ouch, c extension seems to leak objects'
diff --git a/deps/v8_inspector/deps/jinja2/tox.ini b/deps/v8_inspector/deps/jinja2/tox.ini
new file mode 100644
index 0000000000..0daabf75b6
--- /dev/null
+++ b/deps/v8_inspector/deps/jinja2/tox.ini
@@ -0,0 +1,9 @@
+[tox]
+envlist = py26, py27, pypy, py33, py34, py35
+
+[testenv]
+commands =
+ py.test []
+
+deps =
+ pytest
diff --git a/deps/v8_inspector/deps/markupsafe/.gitignore b/deps/v8_inspector/deps/markupsafe/.gitignore
new file mode 100644
index 0000000000..e3a8794391
--- /dev/null
+++ b/deps/v8_inspector/deps/markupsafe/.gitignore
@@ -0,0 +1,10 @@
+.DS_Store
+*.pyc
+*.pyo
+*.o
+*.so
+env
+dist
+build
+.tox
+*.egg-info
diff --git a/deps/v8_inspector/deps/markupsafe/.travis.yml b/deps/v8_inspector/deps/markupsafe/.travis.yml
new file mode 100644
index 0000000000..c0128baf9c
--- /dev/null
+++ b/deps/v8_inspector/deps/markupsafe/.travis.yml
@@ -0,0 +1,11 @@
+sudo: false
+language: python
+python:
+ - "2.6"
+ - "2.7"
+ - "3.3"
+ - "3.4"
+ - "3.5"
+install:
+ - "python setup.py install"
+script: make test
diff --git a/deps/v8_inspector/deps/markupsafe/AUTHORS b/deps/v8_inspector/deps/markupsafe/AUTHORS
new file mode 100644
index 0000000000..f7e2942ecc
--- /dev/null
+++ b/deps/v8_inspector/deps/markupsafe/AUTHORS
@@ -0,0 +1,13 @@
+MarkupSafe is written and maintained by Armin Ronacher and
+various contributors:
+
+Development Lead
+````````````````
+
+- Armin Ronacher <armin.ronacher@active-4.com>
+
+Patches and Suggestions
+```````````````````````
+
+- Georg Brandl
+- Mickaël Guérin
diff --git a/deps/v8_inspector/deps/markupsafe/CHANGES b/deps/v8_inspector/deps/markupsafe/CHANGES
new file mode 100644
index 0000000000..706a230c75
--- /dev/null
+++ b/deps/v8_inspector/deps/markupsafe/CHANGES
@@ -0,0 +1,48 @@
+MarkupSafe Changelog
+====================
+
+Version 1.0
+-----------
+
+- Fixed custom types not invoking `__unicode__` when used
+ with `format()`.
+- Added `__version__` module attribute
+- Improve unescape code to leave lone ampersands alone.
+
+Version 0.18
+------------
+
+- Fixed `__mul__` and string splitting on Python 3.
+
+Version 0.17
+------------
+
+- Fixed a bug with broken interpolation on tuples.
+
+Version 0.16
+------------
+
+- Improved Python 3 Support and removed 2to3
+- Removed support for Python 3.2 and 2.5
+
+Version 0.15
+------------
+
+- Fixed a typo that caused the library to fail to install
+ on pypy and jython -.-
+
+Version 0.14
+------------
+
+- Release fix for 0.13.
+
+Version 0.13
+------------
+
+- Do not attempt to compile extension for PyPy or Jython.
+- Work around some 64bit Windows issues.
+
+Version 0.12
+------------
+
+- improved PyPy compatibility
diff --git a/deps/v8_inspector/deps/markupsafe/LICENSE b/deps/v8_inspector/deps/markupsafe/LICENSE
new file mode 100644
index 0000000000..5d2693890d
--- /dev/null
+++ b/deps/v8_inspector/deps/markupsafe/LICENSE
@@ -0,0 +1,33 @@
+Copyright (c) 2010 by Armin Ronacher and contributors. See AUTHORS
+for more details.
+
+Some rights reserved.
+
+Redistribution and use in source and binary forms of the software as well
+as documentation, with or without modification, are permitted provided
+that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+* The names of the contributors may not be used to endorse or
+ promote products derived from this software without specific
+ prior written permission.
+
+THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
+NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
diff --git a/deps/v8_inspector/deps/markupsafe/MANIFEST.in b/deps/v8_inspector/deps/markupsafe/MANIFEST.in
new file mode 100644
index 0000000000..d50e4e0dc7
--- /dev/null
+++ b/deps/v8_inspector/deps/markupsafe/MANIFEST.in
@@ -0,0 +1,2 @@
+include LICENSE README.rst AUTHORS
+recursive-include markupsafe *.c
diff --git a/deps/v8_inspector/deps/markupsafe/Makefile b/deps/v8_inspector/deps/markupsafe/Makefile
new file mode 100644
index 0000000000..fd263b160a
--- /dev/null
+++ b/deps/v8_inspector/deps/markupsafe/Makefile
@@ -0,0 +1,7 @@
+test:
+ python setup.py test
+
+tox-test:
+ tox
+
+.PYONY: test tox-test
diff --git a/deps/v8_inspector/deps/markupsafe/README.rst b/deps/v8_inspector/deps/markupsafe/README.rst
new file mode 100644
index 0000000000..53dcd023a9
--- /dev/null
+++ b/deps/v8_inspector/deps/markupsafe/README.rst
@@ -0,0 +1,101 @@
+MarkupSafe
+==========
+
+Implements a unicode subclass that supports HTML strings:
+
+>>> from markupsafe import Markup, escape
+>>> escape("<script>alert(document.cookie);</script>")
+Markup(u'&lt;script&gt;alert(document.cookie);&lt;/script&gt;')
+>>> tmpl = Markup("<em>%s</em>")
+>>> tmpl % "Peter > Lustig"
+Markup(u'<em>Peter &gt; Lustig</em>')
+
+If you want to make an object unicode that is not yet unicode
+but don't want to lose the taint information, you can use the
+`soft_unicode` function. (On Python 3 you can also use `soft_str` which
+is a different name for the same function).
+
+>>> from markupsafe import soft_unicode
+>>> soft_unicode(42)
+u'42'
+>>> soft_unicode(Markup('foo'))
+Markup(u'foo')
+
+HTML Representations
+--------------------
+
+Objects can customize their HTML markup equivalent by overriding
+the `__html__` function:
+
+>>> class Foo(object):
+... def __html__(self):
+... return '<strong>Nice</strong>'
+...
+>>> escape(Foo())
+Markup(u'<strong>Nice</strong>')
+>>> Markup(Foo())
+Markup(u'<strong>Nice</strong>')
+
+Silent Escapes
+--------------
+
+Since MarkupSafe 0.10 there is now also a separate escape function
+called `escape_silent` that returns an empty string for `None` for
+consistency with other systems that return empty strings for `None`
+when escaping (for instance Pylons' webhelpers).
+
+If you also want to use this for the escape method of the Markup
+object, you can create your own subclass that does that::
+
+ from markupsafe import Markup, escape_silent as escape
+
+ class SilentMarkup(Markup):
+ __slots__ = ()
+
+ @classmethod
+ def escape(cls, s):
+ return cls(escape(s))
+
+New-Style String Formatting
+---------------------------
+
+Starting with MarkupSafe 0.21 new style string formats from Python 2.6 and
+3.x are now fully supported. Previously the escape behavior of those
+functions was spotty at best. The new implementations operates under the
+following algorithm:
+
+1. if an object has an ``__html_format__`` method it is called as
+ replacement for ``__format__`` with the format specifier. It either
+ has to return a string or markup object.
+2. if an object has an ``__html__`` method it is called.
+3. otherwise the default format system of Python kicks in and the result
+ is HTML escaped.
+
+Here is how you can implement your own formatting::
+
+ class User(object):
+
+ def __init__(self, id, username):
+ self.id = id
+ self.username = username
+
+ def __html_format__(self, format_spec):
+ if format_spec == 'link':
+ return Markup('<a href="/user/{0}">{1}</a>').format(
+ self.id,
+ self.__html__(),
+ )
+ elif format_spec:
+ raise ValueError('Invalid format spec')
+ return self.__html__()
+
+ def __html__(self):
+ return Markup('<span class=user>{0}</span>').format(self.username)
+
+And to format that user:
+
+>>> user = User(1, 'foo')
+>>> Markup('<p>User: {0:link}').format(user)
+Markup(u'<p>User: <a href="/user/1"><span class=user>foo</span></a>')
+
+Markupsafe supports Python 2.6, 2.7 and Python 3.3 and higher.
diff --git a/deps/v8_inspector/deps/markupsafe/bench/bench_basic.py b/deps/v8_inspector/deps/markupsafe/bench/bench_basic.py
new file mode 100644
index 0000000000..1172d150bb
--- /dev/null
+++ b/deps/v8_inspector/deps/markupsafe/bench/bench_basic.py
@@ -0,0 +1,5 @@
+from markupsafe import escape
+
+
+def run():
+ escape('<strong>Hello World!</strong>')
diff --git a/deps/v8_inspector/deps/markupsafe/bench/bench_largestring.py b/deps/v8_inspector/deps/markupsafe/bench/bench_largestring.py
new file mode 100644
index 0000000000..7bde595c10
--- /dev/null
+++ b/deps/v8_inspector/deps/markupsafe/bench/bench_largestring.py
@@ -0,0 +1,6 @@
+from markupsafe import escape
+
+
+def run():
+ string = '<strong>Hello World!</strong>' * 1000
+ escape(string)
diff --git a/deps/v8_inspector/deps/markupsafe/bench/bench_long_empty_string.py b/deps/v8_inspector/deps/markupsafe/bench/bench_long_empty_string.py
new file mode 100644
index 0000000000..320fb0a93b
--- /dev/null
+++ b/deps/v8_inspector/deps/markupsafe/bench/bench_long_empty_string.py
@@ -0,0 +1,6 @@
+from markupsafe import escape
+
+
+def run():
+ string = 'Hello World!' * 1000
+ escape(string)
diff --git a/deps/v8_inspector/deps/markupsafe/bench/bench_long_suffix.py b/deps/v8_inspector/deps/markupsafe/bench/bench_long_suffix.py
new file mode 100644
index 0000000000..43fe56371e
--- /dev/null
+++ b/deps/v8_inspector/deps/markupsafe/bench/bench_long_suffix.py
@@ -0,0 +1,6 @@
+from markupsafe import escape
+
+
+def run():
+ string = '<strong>Hello World!</strong>' + 'x' * 100000
+ escape(string)
diff --git a/deps/v8_inspector/deps/markupsafe/bench/bench_short_empty_string.py b/deps/v8_inspector/deps/markupsafe/bench/bench_short_empty_string.py
new file mode 100644
index 0000000000..91cccc4991
--- /dev/null
+++ b/deps/v8_inspector/deps/markupsafe/bench/bench_short_empty_string.py
@@ -0,0 +1,5 @@
+from markupsafe import escape
+
+
+def run():
+ escape('Hello World!')
diff --git a/deps/v8_inspector/deps/markupsafe/bench/runbench.py b/deps/v8_inspector/deps/markupsafe/bench/runbench.py
new file mode 100644
index 0000000000..2ebdc53c58
--- /dev/null
+++ b/deps/v8_inspector/deps/markupsafe/bench/runbench.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+"""
+ Runs the benchmarks
+"""
+import sys
+import os
+import re
+from subprocess import Popen
+
+_filename_re = re.compile(r'^bench_(.*?)\.py$')
+bench_directory = os.path.abspath(os.path.dirname(__file__))
+
+
+def list_benchmarks():
+ result = []
+ for name in os.listdir(bench_directory):
+ match = _filename_re.match(name)
+ if match is not None:
+ result.append(match.group(1))
+ result.sort(key=lambda x: (x.startswith('logging_'), x.lower()))
+ return result
+
+
+def run_bench(name):
+ sys.stdout.write('%-32s' % name)
+ sys.stdout.flush()
+ Popen([sys.executable, '-mtimeit', '-s',
+ 'from bench_%s import run' % name,
+ 'run()']).wait()
+
+
+def main():
+ print '=' * 80
+ print 'Running benchmark for MarkupSafe'
+ print '-' * 80
+ os.chdir(bench_directory)
+ for bench in list_benchmarks():
+ run_bench(bench)
+ print '-' * 80
+
+
+if __name__ == '__main__':
+ main()
diff --git a/deps/v8_inspector/deps/markupsafe/markupsafe/__init__.py b/deps/v8_inspector/deps/markupsafe/markupsafe/__init__.py
new file mode 100644
index 0000000000..68dc85f612
--- /dev/null
+++ b/deps/v8_inspector/deps/markupsafe/markupsafe/__init__.py
@@ -0,0 +1,305 @@
+# -*- coding: utf-8 -*-
+"""
+ markupsafe
+ ~~~~~~~~~~
+
+ Implements a Markup string.
+
+ :copyright: (c) 2010 by Armin Ronacher.
+ :license: BSD, see LICENSE for more details.
+"""
+import re
+import string
+from collections import Mapping
+from markupsafe._compat import text_type, string_types, int_types, \
+ unichr, iteritems, PY2
+
+__version__ = "1.0"
+
+__all__ = ['Markup', 'soft_unicode', 'escape', 'escape_silent']
+
+
+_striptags_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
+_entity_re = re.compile(r'&([^& ;]+);')
+
+
+class Markup(text_type):
+ r"""Marks a string as being safe for inclusion in HTML/XML output without
+ needing to be escaped. This implements the `__html__` interface a couple
+ of frameworks and web applications use. :class:`Markup` is a direct
+ subclass of `unicode` and provides all the methods of `unicode` just that
+ it escapes arguments passed and always returns `Markup`.
+
+ The `escape` function returns markup objects so that double escaping can't
+ happen.
+
+ The constructor of the :class:`Markup` class can be used for three
+ different things: When passed an unicode object it's assumed to be safe,
+ when passed an object with an HTML representation (has an `__html__`
+ method) that representation is used, otherwise the object passed is
+ converted into a unicode string and then assumed to be safe:
+
+ >>> Markup("Hello <em>World</em>!")
+ Markup(u'Hello <em>World</em>!')
+ >>> class Foo(object):
+ ... def __html__(self):
+ ... return '<a href="#">foo</a>'
+ ...
+ >>> Markup(Foo())
+ Markup(u'<a href="#">foo</a>')
+
+ If you want object passed being always treated as unsafe you can use the
+ :meth:`escape` classmethod to create a :class:`Markup` object:
+
+ >>> Markup.escape("Hello <em>World</em>!")
+ Markup(u'Hello &lt;em&gt;World&lt;/em&gt;!')
+
+ Operations on a markup string are markup aware which means that all
+ arguments are passed through the :func:`escape` function:
+
+ >>> em = Markup("<em>%s</em>")
+ >>> em % "foo & bar"
+ Markup(u'<em>foo &amp; bar</em>')
+ >>> strong = Markup("<strong>%(text)s</strong>")
+ >>> strong % {'text': '<blink>hacker here</blink>'}
+ Markup(u'<strong>&lt;blink&gt;hacker here&lt;/blink&gt;</strong>')
+ >>> Markup("<em>Hello</em> ") + "<foo>"
+ Markup(u'<em>Hello</em> &lt;foo&gt;')
+ """
+ __slots__ = ()
+
+ def __new__(cls, base=u'', encoding=None, errors='strict'):
+ if hasattr(base, '__html__'):
+ base = base.__html__()
+ if encoding is None:
+ return text_type.__new__(cls, base)
+ return text_type.__new__(cls, base, encoding, errors)
+
+ def __html__(self):
+ return self
+
+ def __add__(self, other):
+ if isinstance(other, string_types) or hasattr(other, '__html__'):
+ return self.__class__(super(Markup, self).__add__(self.escape(other)))
+ return NotImplemented
+
+ def __radd__(self, other):
+ if hasattr(other, '__html__') or isinstance(other, string_types):
+ return self.escape(other).__add__(self)
+ return NotImplemented
+
+ def __mul__(self, num):
+ if isinstance(num, int_types):
+ return self.__class__(text_type.__mul__(self, num))
+ return NotImplemented
+ __rmul__ = __mul__
+
+ def __mod__(self, arg):
+ if isinstance(arg, tuple):
+ arg = tuple(_MarkupEscapeHelper(x, self.escape) for x in arg)
+ else:
+ arg = _MarkupEscapeHelper(arg, self.escape)
+ return self.__class__(text_type.__mod__(self, arg))
+
+ def __repr__(self):
+ return '%s(%s)' % (
+ self.__class__.__name__,
+ text_type.__repr__(self)
+ )
+
+ def join(self, seq):
+ return self.__class__(text_type.join(self, map(self.escape, seq)))
+ join.__doc__ = text_type.join.__doc__
+
+ def split(self, *args, **kwargs):
+ return list(map(self.__class__, text_type.split(self, *args, **kwargs)))
+ split.__doc__ = text_type.split.__doc__
+
+ def rsplit(self, *args, **kwargs):
+ return list(map(self.__class__, text_type.rsplit(self, *args, **kwargs)))
+ rsplit.__doc__ = text_type.rsplit.__doc__
+
+ def splitlines(self, *args, **kwargs):
+ return list(map(self.__class__, text_type.splitlines(
+ self, *args, **kwargs)))
+ splitlines.__doc__ = text_type.splitlines.__doc__
+
+ def unescape(self):
+ r"""Unescape markup again into an text_type string. This also resolves
+ known HTML4 and XHTML entities:
+
+ >>> Markup("Main &raquo; <em>About</em>").unescape()
+ u'Main \xbb <em>About</em>'
+ """
+ from markupsafe._constants import HTML_ENTITIES
+ def handle_match(m):
+ name = m.group(1)
+ if name in HTML_ENTITIES:
+ return unichr(HTML_ENTITIES[name])
+ try:
+ if name[:2] in ('#x', '#X'):
+ return unichr(int(name[2:], 16))
+ elif name.startswith('#'):
+ return unichr(int(name[1:]))
+ except ValueError:
+ pass
+ # Don't modify unexpected input.
+ return m.group()
+ return _entity_re.sub(handle_match, text_type(self))
+
+ def striptags(self):
+ r"""Unescape markup into an text_type string and strip all tags. This
+ also resolves known HTML4 and XHTML entities. Whitespace is
+ normalized to one:
+
+ >>> Markup("Main &raquo; <em>About</em>").striptags()
+ u'Main \xbb About'
+ """
+ stripped = u' '.join(_striptags_re.sub('', self).split())
+ return Markup(stripped).unescape()
+
+ @classmethod
+ def escape(cls, s):
+ """Escape the string. Works like :func:`escape` with the difference
+ that for subclasses of :class:`Markup` this function would return the
+ correct subclass.
+ """
+ rv = escape(s)
+ if rv.__class__ is not cls:
+ return cls(rv)
+ return rv
+
+ def make_simple_escaping_wrapper(name):
+ orig = getattr(text_type, name)
+ def func(self, *args, **kwargs):
+ args = _escape_argspec(list(args), enumerate(args), self.escape)
+ _escape_argspec(kwargs, iteritems(kwargs), self.escape)
+ return self.__class__(orig(self, *args, **kwargs))
+ func.__name__ = orig.__name__
+ func.__doc__ = orig.__doc__
+ return func
+
+ for method in '__getitem__', 'capitalize', \
+ 'title', 'lower', 'upper', 'replace', 'ljust', \
+ 'rjust', 'lstrip', 'rstrip', 'center', 'strip', \
+ 'translate', 'expandtabs', 'swapcase', 'zfill':
+ locals()[method] = make_simple_escaping_wrapper(method)
+
+ # new in python 2.5
+ if hasattr(text_type, 'partition'):
+ def partition(self, sep):
+ return tuple(map(self.__class__,
+ text_type.partition(self, self.escape(sep))))
+ def rpartition(self, sep):
+ return tuple(map(self.__class__,
+ text_type.rpartition(self, self.escape(sep))))
+
+ # new in python 2.6
+ if hasattr(text_type, 'format'):
+ def format(*args, **kwargs):
+ self, args = args[0], args[1:]
+ formatter = EscapeFormatter(self.escape)
+ kwargs = _MagicFormatMapping(args, kwargs)
+ return self.__class__(formatter.vformat(self, args, kwargs))
+
+ def __html_format__(self, format_spec):
+ if format_spec:
+ raise ValueError('Unsupported format specification '
+ 'for Markup.')
+ return self
+
+ # not in python 3
+ if hasattr(text_type, '__getslice__'):
+ __getslice__ = make_simple_escaping_wrapper('__getslice__')
+
+ del method, make_simple_escaping_wrapper
+
+
+class _MagicFormatMapping(Mapping):
+ """This class implements a dummy wrapper to fix a bug in the Python
+ standard library for string formatting.
+
+ See http://bugs.python.org/issue13598 for information about why
+ this is necessary.
+ """
+
+ def __init__(self, args, kwargs):
+ self._args = args
+ self._kwargs = kwargs
+ self._last_index = 0
+
+ def __getitem__(self, key):
+ if key == '':
+ idx = self._last_index
+ self._last_index += 1
+ try:
+ return self._args[idx]
+ except LookupError:
+ pass
+ key = str(idx)
+ return self._kwargs[key]
+
+ def __iter__(self):
+ return iter(self._kwargs)
+
+ def __len__(self):
+ return len(self._kwargs)
+
+
+if hasattr(text_type, 'format'):
+ class EscapeFormatter(string.Formatter):
+
+ def __init__(self, escape):
+ self.escape = escape
+
+ def format_field(self, value, format_spec):
+ if hasattr(value, '__html_format__'):
+ rv = value.__html_format__(format_spec)
+ elif hasattr(value, '__html__'):
+ if format_spec:
+ raise ValueError('No format specification allowed '
+ 'when formatting an object with '
+ 'its __html__ method.')
+ rv = value.__html__()
+ else:
+ # We need to make sure the format spec is unicode here as
+ # otherwise the wrong callback methods are invoked. For
+ # instance a byte string there would invoke __str__ and
+ # not __unicode__.
+ rv = string.Formatter.format_field(
+ self, value, text_type(format_spec))
+ return text_type(self.escape(rv))
+
+
+def _escape_argspec(obj, iterable, escape):
+ """Helper for various string-wrapped functions."""
+ for key, value in iterable:
+ if hasattr(value, '__html__') or isinstance(value, string_types):
+ obj[key] = escape(value)
+ return obj
+
+
+class _MarkupEscapeHelper(object):
+ """Helper for Markup.__mod__"""
+
+ def __init__(self, obj, escape):
+ self.obj = obj
+ self.escape = escape
+
+ __getitem__ = lambda s, x: _MarkupEscapeHelper(s.obj[x], s.escape)
+ __unicode__ = __str__ = lambda s: text_type(s.escape(s.obj))
+ __repr__ = lambda s: str(s.escape(repr(s.obj)))
+ __int__ = lambda s: int(s.obj)
+ __float__ = lambda s: float(s.obj)
+
+
+# we have to import it down here as the speedups and native
+# modules imports the markup type which is define above.
+try:
+ from markupsafe._speedups import escape, escape_silent, soft_unicode
+except ImportError:
+ from markupsafe._native import escape, escape_silent, soft_unicode
+
+if not PY2:
+ soft_str = soft_unicode
+ __all__.append('soft_str')
diff --git a/deps/v8_inspector/deps/markupsafe/markupsafe/_compat.py b/deps/v8_inspector/deps/markupsafe/markupsafe/_compat.py
new file mode 100644
index 0000000000..62e5632ad8
--- /dev/null
+++ b/deps/v8_inspector/deps/markupsafe/markupsafe/_compat.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+"""
+ markupsafe._compat
+ ~~~~~~~~~~~~~~~~~~
+
+ Compatibility module for different Python versions.
+
+ :copyright: (c) 2013 by Armin Ronacher.
+ :license: BSD, see LICENSE for more details.
+"""
+import sys
+
+PY2 = sys.version_info[0] == 2
+
+if not PY2:
+ text_type = str
+ string_types = (str,)
+ unichr = chr
+ int_types = (int,)
+ iteritems = lambda x: iter(x.items())
+else:
+ text_type = unicode
+ string_types = (str, unicode)
+ unichr = unichr
+ int_types = (int, long)
+ iteritems = lambda x: x.iteritems()
diff --git a/deps/v8_inspector/deps/markupsafe/markupsafe/_constants.py b/deps/v8_inspector/deps/markupsafe/markupsafe/_constants.py
new file mode 100644
index 0000000000..919bf03c50
--- /dev/null
+++ b/deps/v8_inspector/deps/markupsafe/markupsafe/_constants.py
@@ -0,0 +1,267 @@
+# -*- coding: utf-8 -*-
+"""
+ markupsafe._constants
+ ~~~~~~~~~~~~~~~~~~~~~
+
+ Highlevel implementation of the Markup string.
+
+ :copyright: (c) 2010 by Armin Ronacher.
+ :license: BSD, see LICENSE for more details.
+"""
+
+
+HTML_ENTITIES = {
+ 'AElig': 198,
+ 'Aacute': 193,
+ 'Acirc': 194,
+ 'Agrave': 192,
+ 'Alpha': 913,
+ 'Aring': 197,
+ 'Atilde': 195,
+ 'Auml': 196,
+ 'Beta': 914,
+ 'Ccedil': 199,
+ 'Chi': 935,
+ 'Dagger': 8225,
+ 'Delta': 916,
+ 'ETH': 208,
+ 'Eacute': 201,
+ 'Ecirc': 202,
+ 'Egrave': 200,
+ 'Epsilon': 917,
+ 'Eta': 919,
+ 'Euml': 203,
+ 'Gamma': 915,
+ 'Iacute': 205,
+ 'Icirc': 206,
+ 'Igrave': 204,
+ 'Iota': 921,
+ 'Iuml': 207,
+ 'Kappa': 922,
+ 'Lambda': 923,
+ 'Mu': 924,
+ 'Ntilde': 209,
+ 'Nu': 925,
+ 'OElig': 338,
+ 'Oacute': 211,
+ 'Ocirc': 212,
+ 'Ograve': 210,
+ 'Omega': 937,
+ 'Omicron': 927,
+ 'Oslash': 216,
+ 'Otilde': 213,
+ 'Ouml': 214,
+ 'Phi': 934,
+ 'Pi': 928,
+ 'Prime': 8243,
+ 'Psi': 936,
+ 'Rho': 929,
+ 'Scaron': 352,
+ 'Sigma': 931,
+ 'THORN': 222,
+ 'Tau': 932,
+ 'Theta': 920,
+ 'Uacute': 218,
+ 'Ucirc': 219,
+ 'Ugrave': 217,
+ 'Upsilon': 933,
+ 'Uuml': 220,
+ 'Xi': 926,
+ 'Yacute': 221,
+ 'Yuml': 376,
+ 'Zeta': 918,
+ 'aacute': 225,
+ 'acirc': 226,
+ 'acute': 180,
+ 'aelig': 230,
+ 'agrave': 224,
+ 'alefsym': 8501,
+ 'alpha': 945,
+ 'amp': 38,
+ 'and': 8743,
+ 'ang': 8736,
+ 'apos': 39,
+ 'aring': 229,
+ 'asymp': 8776,
+ 'atilde': 227,
+ 'auml': 228,
+ 'bdquo': 8222,
+ 'beta': 946,
+ 'brvbar': 166,
+ 'bull': 8226,
+ 'cap': 8745,
+ 'ccedil': 231,
+ 'cedil': 184,
+ 'cent': 162,
+ 'chi': 967,
+ 'circ': 710,
+ 'clubs': 9827,
+ 'cong': 8773,
+ 'copy': 169,
+ 'crarr': 8629,
+ 'cup': 8746,
+ 'curren': 164,
+ 'dArr': 8659,
+ 'dagger': 8224,
+ 'darr': 8595,
+ 'deg': 176,
+ 'delta': 948,
+ 'diams': 9830,
+ 'divide': 247,
+ 'eacute': 233,
+ 'ecirc': 234,
+ 'egrave': 232,
+ 'empty': 8709,
+ 'emsp': 8195,
+ 'ensp': 8194,
+ 'epsilon': 949,
+ 'equiv': 8801,
+ 'eta': 951,
+ 'eth': 240,
+ 'euml': 235,
+ 'euro': 8364,
+ 'exist': 8707,
+ 'fnof': 402,
+ 'forall': 8704,
+ 'frac12': 189,
+ 'frac14': 188,
+ 'frac34': 190,
+ 'frasl': 8260,
+ 'gamma': 947,
+ 'ge': 8805,
+ 'gt': 62,
+ 'hArr': 8660,
+ 'harr': 8596,
+ 'hearts': 9829,
+ 'hellip': 8230,
+ 'iacute': 237,
+ 'icirc': 238,
+ 'iexcl': 161,
+ 'igrave': 236,
+ 'image': 8465,
+ 'infin': 8734,
+ 'int': 8747,
+ 'iota': 953,
+ 'iquest': 191,
+ 'isin': 8712,
+ 'iuml': 239,
+ 'kappa': 954,
+ 'lArr': 8656,
+ 'lambda': 955,
+ 'lang': 9001,
+ 'laquo': 171,
+ 'larr': 8592,
+ 'lceil': 8968,
+ 'ldquo': 8220,
+ 'le': 8804,
+ 'lfloor': 8970,
+ 'lowast': 8727,
+ 'loz': 9674,
+ 'lrm': 8206,
+ 'lsaquo': 8249,
+ 'lsquo': 8216,
+ 'lt': 60,
+ 'macr': 175,
+ 'mdash': 8212,
+ 'micro': 181,
+ 'middot': 183,
+ 'minus': 8722,
+ 'mu': 956,
+ 'nabla': 8711,
+ 'nbsp': 160,
+ 'ndash': 8211,
+ 'ne': 8800,
+ 'ni': 8715,
+ 'not': 172,
+ 'notin': 8713,
+ 'nsub': 8836,
+ 'ntilde': 241,
+ 'nu': 957,
+ 'oacute': 243,
+ 'ocirc': 244,
+ 'oelig': 339,
+ 'ograve': 242,
+ 'oline': 8254,
+ 'omega': 969,
+ 'omicron': 959,
+ 'oplus': 8853,
+ 'or': 8744,
+ 'ordf': 170,
+ 'ordm': 186,
+ 'oslash': 248,
+ 'otilde': 245,
+ 'otimes': 8855,
+ 'ouml': 246,
+ 'para': 182,
+ 'part': 8706,
+ 'permil': 8240,
+ 'perp': 8869,
+ 'phi': 966,
+ 'pi': 960,
+ 'piv': 982,
+ 'plusmn': 177,
+ 'pound': 163,
+ 'prime': 8242,
+ 'prod': 8719,
+ 'prop': 8733,
+ 'psi': 968,
+ 'quot': 34,
+ 'rArr': 8658,
+ 'radic': 8730,
+ 'rang': 9002,
+ 'raquo': 187,
+ 'rarr': 8594,
+ 'rceil': 8969,
+ 'rdquo': 8221,
+ 'real': 8476,
+ 'reg': 174,
+ 'rfloor': 8971,
+ 'rho': 961,
+ 'rlm': 8207,
+ 'rsaquo': 8250,
+ 'rsquo': 8217,
+ 'sbquo': 8218,
+ 'scaron': 353,
+ 'sdot': 8901,
+ 'sect': 167,
+ 'shy': 173,
+ 'sigma': 963,
+ 'sigmaf': 962,
+ 'sim': 8764,
+ 'spades': 9824,
+ 'sub': 8834,
+ 'sube': 8838,
+ 'sum': 8721,
+ 'sup': 8835,
+ 'sup1': 185,
+ 'sup2': 178,
+ 'sup3': 179,
+ 'supe': 8839,
+ 'szlig': 223,
+ 'tau': 964,
+ 'there4': 8756,
+ 'theta': 952,
+ 'thetasym': 977,
+ 'thinsp': 8201,
+ 'thorn': 254,
+ 'tilde': 732,
+ 'times': 215,
+ 'trade': 8482,
+ 'uArr': 8657,
+ 'uacute': 250,
+ 'uarr': 8593,
+ 'ucirc': 251,
+ 'ugrave': 249,
+ 'uml': 168,
+ 'upsih': 978,
+ 'upsilon': 965,
+ 'uuml': 252,
+ 'weierp': 8472,
+ 'xi': 958,
+ 'yacute': 253,
+ 'yen': 165,
+ 'yuml': 255,
+ 'zeta': 950,
+ 'zwj': 8205,
+ 'zwnj': 8204
+}
diff --git a/deps/v8_inspector/deps/markupsafe/markupsafe/_native.py b/deps/v8_inspector/deps/markupsafe/markupsafe/_native.py
new file mode 100644
index 0000000000..5e83f10a11
--- /dev/null
+++ b/deps/v8_inspector/deps/markupsafe/markupsafe/_native.py
@@ -0,0 +1,46 @@
+# -*- coding: utf-8 -*-
+"""
+ markupsafe._native
+ ~~~~~~~~~~~~~~~~~~
+
+ Native Python implementation the C module is not compiled.
+
+ :copyright: (c) 2010 by Armin Ronacher.
+ :license: BSD, see LICENSE for more details.
+"""
+from markupsafe import Markup
+from markupsafe._compat import text_type
+
+
+def escape(s):
+ """Convert the characters &, <, >, ' and " in string s to HTML-safe
+ sequences. Use this if you need to display text that might contain
+ such characters in HTML. Marks return value as markup string.
+ """
+ if hasattr(s, '__html__'):
+ return s.__html__()
+ return Markup(text_type(s)
+ .replace('&', '&amp;')
+ .replace('>', '&gt;')
+ .replace('<', '&lt;')
+ .replace("'", '&#39;')
+ .replace('"', '&#34;')
+ )
+
+
+def escape_silent(s):
+ """Like :func:`escape` but converts `None` into an empty
+ markup string.
+ """
+ if s is None:
+ return Markup()
+ return escape(s)
+
+
+def soft_unicode(s):
+ """Make a string unicode if it isn't already. That way a markup
+ string is not converted back to unicode.
+ """
+ if not isinstance(s, text_type):
+ s = text_type(s)
+ return s
diff --git a/deps/v8_inspector/deps/markupsafe/markupsafe/_speedups.c b/deps/v8_inspector/deps/markupsafe/markupsafe/_speedups.c
new file mode 100644
index 0000000000..d779a68cc5
--- /dev/null
+++ b/deps/v8_inspector/deps/markupsafe/markupsafe/_speedups.c
@@ -0,0 +1,239 @@
+/**
+ * markupsafe._speedups
+ * ~~~~~~~~~~~~~~~~~~~~
+ *
+ * This module implements functions for automatic escaping in C for better
+ * performance.
+ *
+ * :copyright: (c) 2010 by Armin Ronacher.
+ * :license: BSD.
+ */
+
+#include <Python.h>
+
+#define ESCAPED_CHARS_TABLE_SIZE 63
+#define UNICHR(x) (PyUnicode_AS_UNICODE((PyUnicodeObject*)PyUnicode_DecodeASCII(x, strlen(x), NULL)));
+
+#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
+typedef int Py_ssize_t;
+#define PY_SSIZE_T_MAX INT_MAX
+#define PY_SSIZE_T_MIN INT_MIN
+#endif
+
+
+static PyObject* markup;
+static Py_ssize_t escaped_chars_delta_len[ESCAPED_CHARS_TABLE_SIZE];
+static Py_UNICODE *escaped_chars_repl[ESCAPED_CHARS_TABLE_SIZE];
+
+static int
+init_constants(void)
+{
+ PyObject *module;
+ /* mapping of characters to replace */
+ escaped_chars_repl['"'] = UNICHR("&#34;");
+ escaped_chars_repl['\''] = UNICHR("&#39;");
+ escaped_chars_repl['&'] = UNICHR("&amp;");
+ escaped_chars_repl['<'] = UNICHR("&lt;");
+ escaped_chars_repl['>'] = UNICHR("&gt;");
+
+ /* lengths of those characters when replaced - 1 */
+ memset(escaped_chars_delta_len, 0, sizeof (escaped_chars_delta_len));
+ escaped_chars_delta_len['"'] = escaped_chars_delta_len['\''] = \
+ escaped_chars_delta_len['&'] = 4;
+ escaped_chars_delta_len['<'] = escaped_chars_delta_len['>'] = 3;
+
+ /* import markup type so that we can mark the return value */
+ module = PyImport_ImportModule("markupsafe");
+ if (!module)
+ return 0;
+ markup = PyObject_GetAttrString(module, "Markup");
+ Py_DECREF(module);
+
+ return 1;
+}
+
+static PyObject*
+escape_unicode(PyUnicodeObject *in)
+{
+ PyUnicodeObject *out;
+ Py_UNICODE *inp = PyUnicode_AS_UNICODE(in);
+ const Py_UNICODE *inp_end = PyUnicode_AS_UNICODE(in) + PyUnicode_GET_SIZE(in);
+ Py_UNICODE *next_escp;
+ Py_UNICODE *outp;
+ Py_ssize_t delta=0, erepl=0, delta_len=0;
+
+ /* First we need to figure out how long the escaped string will be */
+ while (*(inp) || inp < inp_end) {
+ if (*inp < ESCAPED_CHARS_TABLE_SIZE) {
+ delta += escaped_chars_delta_len[*inp];
+ erepl += !!escaped_chars_delta_len[*inp];
+ }
+ ++inp;
+ }
+
+ /* Do we need to escape anything at all? */
+ if (!erepl) {
+ Py_INCREF(in);
+ return (PyObject*)in;
+ }
+
+ out = (PyUnicodeObject*)PyUnicode_FromUnicode(NULL, PyUnicode_GET_SIZE(in) + delta);
+ if (!out)
+ return NULL;
+
+ outp = PyUnicode_AS_UNICODE(out);
+ inp = PyUnicode_AS_UNICODE(in);
+ while (erepl-- > 0) {
+ /* look for the next substitution */
+ next_escp = inp;
+ while (next_escp < inp_end) {
+ if (*next_escp < ESCAPED_CHARS_TABLE_SIZE &&
+ (delta_len = escaped_chars_delta_len[*next_escp])) {
+ ++delta_len;
+ break;
+ }
+ ++next_escp;
+ }
+
+ if (next_escp > inp) {
+ /* copy unescaped chars between inp and next_escp */
+ Py_UNICODE_COPY(outp, inp, next_escp-inp);
+ outp += next_escp - inp;
+ }
+
+ /* escape 'next_escp' */
+ Py_UNICODE_COPY(outp, escaped_chars_repl[*next_escp], delta_len);
+ outp += delta_len;
+
+ inp = next_escp + 1;
+ }
+ if (inp < inp_end)
+ Py_UNICODE_COPY(outp, inp, PyUnicode_GET_SIZE(in) - (inp - PyUnicode_AS_UNICODE(in)));
+
+ return (PyObject*)out;
+}
+
+
+static PyObject*
+escape(PyObject *self, PyObject *text)
+{
+ PyObject *s = NULL, *rv = NULL, *html;
+
+ /* we don't have to escape integers, bools or floats */
+ if (PyLong_CheckExact(text) ||
+#if PY_MAJOR_VERSION < 3
+ PyInt_CheckExact(text) ||
+#endif
+ PyFloat_CheckExact(text) || PyBool_Check(text) ||
+ text == Py_None)
+ return PyObject_CallFunctionObjArgs(markup, text, NULL);
+
+ /* if the object has an __html__ method that performs the escaping */
+ html = PyObject_GetAttrString(text, "__html__");
+ if (html) {
+ rv = PyObject_CallObject(html, NULL);
+ Py_DECREF(html);
+ return rv;
+ }
+
+ /* otherwise make the object unicode if it isn't, then escape */
+ PyErr_Clear();
+ if (!PyUnicode_Check(text)) {
+#if PY_MAJOR_VERSION < 3
+ PyObject *unicode = PyObject_Unicode(text);
+#else
+ PyObject *unicode = PyObject_Str(text);
+#endif
+ if (!unicode)
+ return NULL;
+ s = escape_unicode((PyUnicodeObject*)unicode);
+ Py_DECREF(unicode);
+ }
+ else
+ s = escape_unicode((PyUnicodeObject*)text);
+
+ /* convert the unicode string into a markup object. */
+ rv = PyObject_CallFunctionObjArgs(markup, (PyObject*)s, NULL);
+ Py_DECREF(s);
+ return rv;
+}
+
+
+static PyObject*
+escape_silent(PyObject *self, PyObject *text)
+{
+ if (text != Py_None)
+ return escape(self, text);
+ return PyObject_CallFunctionObjArgs(markup, NULL);
+}
+
+
+static PyObject*
+soft_unicode(PyObject *self, PyObject *s)
+{
+ if (!PyUnicode_Check(s))
+#if PY_MAJOR_VERSION < 3
+ return PyObject_Unicode(s);
+#else
+ return PyObject_Str(s);
+#endif
+ Py_INCREF(s);
+ return s;
+}
+
+
+static PyMethodDef module_methods[] = {
+ {"escape", (PyCFunction)escape, METH_O,
+ "escape(s) -> markup\n\n"
+ "Convert the characters &, <, >, ', and \" in string s to HTML-safe\n"
+ "sequences. Use this if you need to display text that might contain\n"
+ "such characters in HTML. Marks return value as markup string."},
+ {"escape_silent", (PyCFunction)escape_silent, METH_O,
+ "escape_silent(s) -> markup\n\n"
+ "Like escape but converts None to an empty string."},
+ {"soft_unicode", (PyCFunction)soft_unicode, METH_O,
+ "soft_unicode(object) -> string\n\n"
+ "Make a string unicode if it isn't already. That way a markup\n"
+ "string is not converted back to unicode."},
+ {NULL, NULL, 0, NULL} /* Sentinel */
+};
+
+
+#if PY_MAJOR_VERSION < 3
+
+#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
+#define PyMODINIT_FUNC void
+#endif
+PyMODINIT_FUNC
+init_speedups(void)
+{
+ if (!init_constants())
+ return;
+
+ Py_InitModule3("markupsafe._speedups", module_methods, "");
+}
+
+#else /* Python 3.x module initialization */
+
+static struct PyModuleDef module_definition = {
+ PyModuleDef_HEAD_INIT,
+ "markupsafe._speedups",
+ NULL,
+ -1,
+ module_methods,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+PyMODINIT_FUNC
+PyInit__speedups(void)
+{
+ if (!init_constants())
+ return NULL;
+
+ return PyModule_Create(&module_definition);
+}
+
+#endif
diff --git a/deps/v8_inspector/deps/markupsafe/markupsafe/tests.py b/deps/v8_inspector/deps/markupsafe/markupsafe/tests.py
new file mode 100644
index 0000000000..f3e2379e0c
--- /dev/null
+++ b/deps/v8_inspector/deps/markupsafe/markupsafe/tests.py
@@ -0,0 +1,207 @@
+# -*- coding: utf-8 -*-
+import gc
+import sys
+import unittest
+from markupsafe import Markup, escape, escape_silent
+from markupsafe._compat import text_type, PY2
+
+
+class MarkupTestCase(unittest.TestCase):
+
+ def test_adding(self):
+ # adding two strings should escape the unsafe one
+ unsafe = '<script type="application/x-some-script">alert("foo");</script>'
+ safe = Markup('<em>username</em>')
+ assert unsafe + safe == text_type(escape(unsafe)) + text_type(safe)
+
+ def test_string_interpolation(self):
+ # string interpolations are safe to use too
+ assert Markup('<em>%s</em>') % '<bad user>' == \
+ '<em>&lt;bad user&gt;</em>'
+ assert Markup('<em>%(username)s</em>') % {
+ 'username': '<bad user>'
+ } == '<em>&lt;bad user&gt;</em>'
+
+ assert Markup('%i') % 3.14 == '3'
+ assert Markup('%.2f') % 3.14 == '3.14'
+
+ def test_type_behavior(self):
+ # an escaped object is markup too
+ assert type(Markup('foo') + 'bar') is Markup
+
+ # and it implements __html__ by returning itself
+ x = Markup("foo")
+ assert x.__html__() is x
+
+ def test_html_interop(self):
+ # it also knows how to treat __html__ objects
+ class Foo(object):
+ def __html__(self):
+ return '<em>awesome</em>'
+ def __unicode__(self):
+ return 'awesome'
+ __str__ = __unicode__
+ assert Markup(Foo()) == '<em>awesome</em>'
+ assert Markup('<strong>%s</strong>') % Foo() == \
+ '<strong><em>awesome</em></strong>'
+
+ def test_tuple_interpol(self):
+ self.assertEqual(Markup('<em>%s:%s</em>') % (
+ '<foo>',
+ '<bar>',
+ ), Markup(u'<em>&lt;foo&gt;:&lt;bar&gt;</em>'))
+
+ def test_dict_interpol(self):
+ self.assertEqual(Markup('<em>%(foo)s</em>') % {
+ 'foo': '<foo>',
+ }, Markup(u'<em>&lt;foo&gt;</em>'))
+ self.assertEqual(Markup('<em>%(foo)s:%(bar)s</em>') % {
+ 'foo': '<foo>',
+ 'bar': '<bar>',
+ }, Markup(u'<em>&lt;foo&gt;:&lt;bar&gt;</em>'))
+
+ def test_escaping(self):
+ # escaping
+ assert escape('"<>&\'') == '&#34;&lt;&gt;&amp;&#39;'
+ assert Markup("<em>Foo &amp; Bar</em>").striptags() == "Foo & Bar"
+
+ def test_unescape(self):
+ assert Markup("&lt;test&gt;").unescape() == "<test>"
+ assert "jack & tavi are cooler than mike & russ" == \
+ Markup("jack & tavi are cooler than mike &amp; russ").unescape(), \
+ Markup("jack & tavi are cooler than mike &amp; russ").unescape()
+
+ # Test that unescape is idempotent
+ original = '&foo&#x3b;'
+ once = Markup(original).unescape()
+ twice = Markup(once).unescape()
+ expected = "&foo;"
+ assert expected == once == twice, (once, twice)
+
+ def test_formatting(self):
+ for actual, expected in (
+ (Markup('%i') % 3.14, '3'),
+ (Markup('%.2f') % 3.14159, '3.14'),
+ (Markup('%s %s %s') % ('<', 123, '>'), '&lt; 123 &gt;'),
+ (Markup('<em>{awesome}</em>').format(awesome='<awesome>'),
+ '<em>&lt;awesome&gt;</em>'),
+ (Markup('{0[1][bar]}').format([0, {'bar': '<bar/>'}]),
+ '&lt;bar/&gt;'),
+ (Markup('{0[1][bar]}').format([0, {'bar': Markup('<bar/>')}]),
+ '<bar/>')):
+ assert actual == expected, "%r should be %r!" % (actual, expected)
+
+ # This is new in 2.7
+ if sys.version_info >= (2, 7):
+ def test_formatting_empty(self):
+ formatted = Markup('{}').format(0)
+ assert formatted == Markup('0')
+
+ def test_custom_formatting(self):
+ class HasHTMLOnly(object):
+ def __html__(self):
+ return Markup('<foo>')
+
+ class HasHTMLAndFormat(object):
+ def __html__(self):
+ return Markup('<foo>')
+ def __html_format__(self, spec):
+ return Markup('<FORMAT>')
+
+ assert Markup('{0}').format(HasHTMLOnly()) == Markup('<foo>')
+ assert Markup('{0}').format(HasHTMLAndFormat()) == Markup('<FORMAT>')
+
+ def test_complex_custom_formatting(self):
+ class User(object):
+ def __init__(self, id, username):
+ self.id = id
+ self.username = username
+ def __html_format__(self, format_spec):
+ if format_spec == 'link':
+ return Markup('<a href="/user/{0}">{1}</a>').format(
+ self.id,
+ self.__html__(),
+ )
+ elif format_spec:
+ raise ValueError('Invalid format spec')
+ return self.__html__()
+ def __html__(self):
+ return Markup('<span class=user>{0}</span>').format(self.username)
+
+ user = User(1, 'foo')
+ assert Markup('<p>User: {0:link}').format(user) == \
+ Markup('<p>User: <a href="/user/1"><span class=user>foo</span></a>')
+
+ def test_formatting_with_objects(self):
+ class Stringable(object):
+ def __unicode__(self):
+ return u'строка'
+ if PY2:
+ def __str__(self):
+ return 'some other value'
+ else:
+ __str__ = __unicode__
+
+ assert Markup('{s}').format(s=Stringable()) == \
+ Markup(u'строка')
+
+ def test_all_set(self):
+ import markupsafe as markup
+ for item in markup.__all__:
+ getattr(markup, item)
+
+ def test_escape_silent(self):
+ assert escape_silent(None) == Markup()
+ assert escape(None) == Markup(None)
+ assert escape_silent('<foo>') == Markup(u'&lt;foo&gt;')
+
+ def test_splitting(self):
+ self.assertEqual(Markup('a b').split(), [
+ Markup('a'),
+ Markup('b')
+ ])
+ self.assertEqual(Markup('a b').rsplit(), [
+ Markup('a'),
+ Markup('b')
+ ])
+ self.assertEqual(Markup('a\nb').splitlines(), [
+ Markup('a'),
+ Markup('b')
+ ])
+
+ def test_mul(self):
+ self.assertEqual(Markup('a') * 3, Markup('aaa'))
+
+
+class MarkupLeakTestCase(unittest.TestCase):
+
+ def test_markup_leaks(self):
+ counts = set()
+ for count in range(20):
+ for item in range(1000):
+ escape("foo")
+ escape("<foo>")
+ escape(u"foo")
+ escape(u"<foo>")
+ if hasattr(sys, 'pypy_version_info'):
+ gc.collect()
+ counts.add(len(gc.get_objects()))
+ assert len(counts) == 1, 'ouch, c extension seems to ' \
+ 'leak objects, got: ' + str(len(counts))
+
+
+def suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(MarkupTestCase))
+
+ # this test only tests the c extension
+ if not hasattr(escape, 'func_code'):
+ suite.addTest(unittest.makeSuite(MarkupLeakTestCase))
+
+ return suite
+
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='suite')
+
+# vim:sts=4:sw=4:et:
diff --git a/deps/v8_inspector/deps/markupsafe/setup.py b/deps/v8_inspector/deps/markupsafe/setup.py
new file mode 100644
index 0000000000..aff786d5e9
--- /dev/null
+++ b/deps/v8_inspector/deps/markupsafe/setup.py
@@ -0,0 +1,133 @@
+import os
+import re
+import ast
+import sys
+from setuptools import setup, Extension, Feature
+from distutils.command.build_ext import build_ext
+from distutils.errors import CCompilerError, DistutilsExecError, \
+ DistutilsPlatformError
+
+
+# fail safe compilation shamelessly stolen from the simplejson
+# setup.py file. Original author: Bob Ippolito
+
+is_jython = 'java' in sys.platform
+is_pypy = hasattr(sys, 'pypy_version_info')
+
+with open('markupsafe/__init__.py') as f:
+ version = ast.literal_eval(re.search(
+ '^__version__\s+=\s+(.*?)$(?sm)', f.read()).group(1))
+
+
+speedups = Feature(
+ 'optional C speed-enhancement module',
+ standard=True,
+ ext_modules=[
+ Extension('markupsafe._speedups', ['markupsafe/_speedups.c']),
+ ],
+)
+
+# Known errors when running build_ext.build_extension method
+ext_errors = (CCompilerError, DistutilsExecError, DistutilsPlatformError)
+if sys.platform == 'win32' and sys.version_info > (2, 6):
+ # 2.6's distutils.msvc9compiler can raise an IOError when failing to
+ # find the compiler
+ ext_errors += (IOError,)
+# Known errors when running build_ext.run method
+run_errors = (DistutilsPlatformError,)
+if sys.platform == 'darwin':
+ run_errors += (SystemError,)
+
+
+class BuildFailed(Exception):
+ pass
+
+
+class ve_build_ext(build_ext):
+ """This class allows C extension building to fail."""
+
+ def run(self):
+ try:
+ build_ext.run(self)
+ except run_errors:
+ raise BuildFailed()
+
+ def build_extension(self, ext):
+ try:
+ build_ext.build_extension(self, ext)
+ except ext_errors:
+ raise BuildFailed()
+ except ValueError:
+ # this can happen on Windows 64 bit, see Python issue 7511
+ if "'path'" in str(sys.exc_info()[1]): # works with Python 2 and 3
+ raise BuildFailed()
+ raise
+
+
+def echo(msg=''):
+ sys.stdout.write(msg + '\n')
+
+
+readme = open(os.path.join(os.path.dirname(__file__), 'README.rst')).read()
+
+
+def run_setup(with_binary):
+ features = {}
+ if with_binary:
+ features['speedups'] = speedups
+ setup(
+ name='MarkupSafe',
+ version=version,
+ url='http://github.com/mitsuhiko/markupsafe',
+ license='BSD',
+ author='Armin Ronacher',
+ author_email='armin.ronacher@active-4.com',
+ description='Implements a XML/HTML/XHTML Markup safe string for Python',
+ long_description=readme,
+ zip_safe=False,
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Web Environment',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: BSD License',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 3',
+ 'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
+ 'Topic :: Software Development :: Libraries :: Python Modules',
+ 'Topic :: Text Processing :: Markup :: HTML'
+ ],
+ packages=['markupsafe'],
+ test_suite='markupsafe.tests.suite',
+ include_package_data=True,
+ cmdclass={'build_ext': ve_build_ext},
+ features=features,
+ )
+
+
+def try_building_extension():
+ try:
+ run_setup(True)
+ except BuildFailed:
+ LINE = '=' * 74
+ BUILD_EXT_WARNING = 'WARNING: The C extension could not be ' \
+ 'compiled, speedups are not enabled.'
+
+ echo(LINE)
+ echo(BUILD_EXT_WARNING)
+ echo('Failure information, if any, is above.')
+ echo('Retrying the build without the C extension now.')
+ echo()
+
+ run_setup(False)
+
+ echo(LINE)
+ echo(BUILD_EXT_WARNING)
+ echo('Plain-Python installation succeeded.')
+ echo(LINE)
+
+
+if not (is_pypy or is_jython):
+ try_building_extension()
+else:
+ run_setup(False)
diff --git a/deps/v8_inspector/deps/markupsafe/tox.ini b/deps/v8_inspector/deps/markupsafe/tox.ini
new file mode 100644
index 0000000000..9b854eb2bf
--- /dev/null
+++ b/deps/v8_inspector/deps/markupsafe/tox.ini
@@ -0,0 +1,5 @@
+[tox]
+envlist = py26, py27, pypy, py33, py34, py35
+
+[testenv]
+commands = python setup.py test
diff --git a/deps/v8_inspector/deps/wtf/README.md b/deps/v8_inspector/deps/wtf/README.md
new file mode 100644
index 0000000000..6fe75ce24c
--- /dev/null
+++ b/deps/v8_inspector/deps/wtf/README.md
@@ -0,0 +1 @@
+# wtf
diff --git a/deps/v8_inspector/deps/wtf/wtf/Assertions.h b/deps/v8_inspector/deps/wtf/wtf/Assertions.h
new file mode 100644
index 0000000000..18f21cacb7
--- /dev/null
+++ b/deps/v8_inspector/deps/wtf/wtf/Assertions.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WTF_Assertions_h
+#define WTF_Assertions_h
+
+#ifndef CHECK
+#define CHECK(condition) ((void) 0)
+#endif
+#define DCHECK(condition) ((void) 0)
+#define NOTREACHED()
+#define DCHECK_GE(i, j) DCHECK(i >= j)
+
+template <typename T>
+inline void USE(T) { }
+
+#endif /* WTF_Assertions_h */
diff --git a/deps/v8_inspector/deps/wtf/wtf/Compiler.h b/deps/v8_inspector/deps/wtf/wtf/Compiler.h
new file mode 100644
index 0000000000..61926a054f
--- /dev/null
+++ b/deps/v8_inspector/deps/wtf/wtf/Compiler.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WTF_Compiler_h
+#define WTF_Compiler_h
+
+/* COMPILER() - the compiler being used to build the project */
+#define COMPILER(WTF_FEATURE) (defined WTF_COMPILER_##WTF_FEATURE && WTF_COMPILER_##WTF_FEATURE)
+
+/* ==== COMPILER() - the compiler being used to build the project ==== */
+
+/* COMPILER(CLANG) - Clang */
+#if defined(__clang__)
+#define WTF_COMPILER_CLANG 1
+#endif
+
+/* COMPILER(MSVC) - Microsoft Visual C++ (and Clang when compiling for Windows). */
+#if defined(_MSC_VER)
+#define WTF_COMPILER_MSVC 1
+#endif
+
+/* COMPILER(GCC) - GNU Compiler Collection (and Clang when compiling for platforms other than Windows). */
+#if defined(__GNUC__)
+#define WTF_COMPILER_GCC 1
+#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+#define GCC_VERSION_AT_LEAST(major, minor, patch) (GCC_VERSION >= (major * 10000 + minor * 100 + patch))
+#else
+/* Define this for !GCC compilers, just so we can write things like GCC_VERSION_AT_LEAST(4, 1, 0). */
+#define GCC_VERSION_AT_LEAST(major, minor, patch) 0
+#endif
+
+#endif /* WTF_Compiler_h */
diff --git a/deps/v8_inspector/deps/wtf/wtf/PtrUtil.h b/deps/v8_inspector/deps/wtf/wtf/PtrUtil.h
new file mode 100644
index 0000000000..0d5a7fdd81
--- /dev/null
+++ b/deps/v8_inspector/deps/wtf/wtf/PtrUtil.h
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef WTF_PtrUtil_h
+#define WTF_PtrUtil_h
+
+#include "wtf/Assertions.h"
+#include <memory>
+
+#if defined(__APPLE__) && !defined(_LIBCPP_VERSION)
+
+namespace std {
+
+template <typename T1, typename T2>
+struct is_convertible
+{
+private:
+ struct True_ { char x[2]; };
+ struct False_ { };
+
+ static True_ helper(T2 const &);
+ static False_ helper(...);
+
+public:
+ static bool const value = (
+ sizeof(True_) == sizeof(is_convertible::helper(T1()))
+ );
+};
+
+template <bool, class T = void>
+struct enable_if {};
+
+template <class T>
+struct enable_if<true, T>
+{
+ typedef T type;
+};
+
+template<class T>
+struct remove_extent { typedef T type; };
+
+template<class T>
+struct remove_extent<T[]> { typedef T type; };
+
+template<class T, std::size_t N>
+struct remove_extent<T[N]> { typedef T type;};
+
+typedef decltype(nullptr) nullptr_t;
+
+template<class T, T v>
+struct integral_constant {
+ static constexpr T value = v;
+ typedef T value_type;
+ typedef integral_constant type;
+ constexpr operator value_type() const noexcept { return value; }
+ constexpr value_type operator()() const noexcept { return value; } //since c++14
+};
+
+typedef integral_constant<bool, true> true_type;
+typedef integral_constant<bool, false> false_type;
+
+template<class T>
+struct is_array : false_type {};
+
+template<class T>
+struct is_array<T[]> : true_type {};
+
+template<class T, std::size_t N>
+struct is_array<T[N]> : true_type {};
+
+template <typename T>
+struct OwnedPtrDeleter {
+ static void deletePtr(T* ptr)
+ {
+ static_assert(sizeof(T) > 0, "type must be complete");
+ delete ptr;
+ }
+};
+
+template <typename T>
+struct OwnedPtrDeleter<T[]> {
+ static void deletePtr(T* ptr)
+ {
+ static_assert(sizeof(T) > 0, "type must be complete");
+ delete[] ptr;
+ }
+};
+
+template <class T, int n>
+struct OwnedPtrDeleter<T[n]> {
+ static_assert(sizeof(T) < 0, "do not use array with size as type");
+};
+
+
+template <typename T> class unique_ptr {
+public:
+ typedef typename remove_extent<T>::type ValueType;
+ typedef ValueType* PtrType;
+
+ unique_ptr() : m_ptr(nullptr) {}
+ unique_ptr(std::nullptr_t) : m_ptr(nullptr) {}
+ unique_ptr(unique_ptr&&);
+ template <typename U, typename = typename enable_if<is_convertible<U*, T*>::value>::type> unique_ptr(unique_ptr<U>&&);
+
+ ~unique_ptr()
+ {
+ OwnedPtrDeleter<T>::deletePtr(m_ptr);
+ m_ptr = nullptr;
+ }
+
+ PtrType get() const { return m_ptr; }
+
+ void reset(PtrType ptr = nullptr);
+ PtrType release();
+
+ ValueType& operator*() const { DCHECK(m_ptr); return *m_ptr; }
+ PtrType operator->() const { DCHECK(m_ptr); return m_ptr; }
+
+ ValueType& operator[](std::ptrdiff_t i) const;
+
+ bool operator!() const { return !m_ptr; }
+ explicit operator bool() const { return m_ptr; }
+
+ unique_ptr& operator=(std::nullptr_t) { reset(); return *this; }
+
+
+ unique_ptr& operator=(unique_ptr&&);
+ template <typename U> unique_ptr& operator=(unique_ptr<U>&&);
+
+ void swap(unique_ptr& o) { std::swap(m_ptr, o.m_ptr); }
+
+ static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
+
+ explicit unique_ptr(PtrType ptr) : m_ptr(ptr) {}
+
+private:
+
+ // We should never have two unique_ptrs for the same underlying object
+ // (otherwise we'll get double-destruction), so these equality operators
+ // should never be needed.
+ template <typename U> bool operator==(const unique_ptr<U>&) const
+ {
+ static_assert(!sizeof(U*), "unique_ptrs should never be equal");
+ return false;
+ }
+ template <typename U> bool operator!=(const unique_ptr<U>&) const
+ {
+ static_assert(!sizeof(U*), "unique_ptrs should never be equal");
+ return false;
+ }
+
+ PtrType m_ptr;
+};
+
+
+template <typename T> inline void unique_ptr<T>::reset(PtrType ptr)
+{
+ PtrType p = m_ptr;
+ m_ptr = ptr;
+ OwnedPtrDeleter<T>::deletePtr(p);
+}
+
+template <typename T> inline typename unique_ptr<T>::PtrType unique_ptr<T>::release()
+{
+ PtrType ptr = m_ptr;
+ m_ptr = nullptr;
+ return ptr;
+}
+
+template <typename T> inline typename unique_ptr<T>::ValueType& unique_ptr<T>::operator[](std::ptrdiff_t i) const
+{
+ static_assert(is_array<T>::value, "elements access is possible for arrays only");
+ DCHECK(m_ptr);
+ DCHECK(i >= 0);
+ return m_ptr[i];
+}
+
+template <typename T> inline unique_ptr<T>::unique_ptr(unique_ptr<T>&& o)
+ : m_ptr(o.release())
+{
+}
+
+template <typename T>
+template <typename U, typename> inline unique_ptr<T>::unique_ptr(unique_ptr<U>&& o)
+ : m_ptr(o.release())
+{
+ static_assert(!is_array<T>::value, "pointers to array must never be converted");
+}
+
+template <typename T> inline unique_ptr<T>& unique_ptr<T>::operator=(unique_ptr<T>&& o)
+{
+ PtrType ptr = m_ptr;
+ m_ptr = o.release();
+ DCHECK(!ptr || m_ptr != ptr);
+ OwnedPtrDeleter<T>::deletePtr(ptr);
+
+ return *this;
+}
+
+template <typename T>
+template <typename U> inline unique_ptr<T>& unique_ptr<T>::operator=(unique_ptr<U>&& o)
+{
+ static_assert(!is_array<T>::value, "pointers to array must never be converted");
+ PtrType ptr = m_ptr;
+ m_ptr = o.release();
+ DCHECK(!ptr || m_ptr != ptr);
+ OwnedPtrDeleter<T>::deletePtr(ptr);
+
+ return *this;
+}
+
+template <typename T> inline void swap(unique_ptr<T>& a, unique_ptr<T>& b)
+{
+ a.swap(b);
+}
+
+template <typename T, typename U> inline bool operator==(const unique_ptr<T>& a, U* b)
+{
+ return a.get() == b;
+}
+
+template <typename T, typename U> inline bool operator==(T* a, const unique_ptr<U>& b)
+{
+ return a == b.get();
+}
+
+template <typename T, typename U> inline bool operator!=(const unique_ptr<T>& a, U* b)
+{
+ return a.get() != b;
+}
+
+template <typename T, typename U> inline bool operator!=(T* a, const unique_ptr<U>& b)
+{
+ return a != b.get();
+}
+
+template <typename T> inline typename unique_ptr<T>::PtrType getPtr(const unique_ptr<T>& p)
+{
+ return p.get();
+}
+
+template <typename T>
+unique_ptr<T> move(unique_ptr<T>& ptr)
+{
+ return unique_ptr<T>(ptr.release());
+}
+
+}
+
+#endif
+
+template <typename T>
+std::unique_ptr<T> wrapUnique(T* ptr) {
+ return std::unique_ptr<T>(ptr);
+}
+
+#endif // WTF_PtrUtil_h
diff --git a/deps/v8_inspector/devtools/Inspector-1.1.json b/deps/v8_inspector/devtools/Inspector-1.1.json
new file mode 100644
index 0000000000..55afa73e9d
--- /dev/null
+++ b/deps/v8_inspector/devtools/Inspector-1.1.json
@@ -0,0 +1,3924 @@
+{
+ "version": { "major": "1", "minor": "1" },
+ "domains": [{
+ "domain": "Inspector",
+ "hidden": true,
+ "types": [],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables inspector domain notifications."
+ },
+ {
+ "name": "disable",
+ "description": "Disables inspector domain notifications."
+ },
+ {
+ "name": "reset",
+ "description": "Resets all domains."
+ }
+ ],
+ "events": [
+ {
+ "name": "evaluateForTestInFrontend",
+ "parameters": [
+ { "name": "testCallId", "type": "integer" },
+ { "name": "script", "type": "string" }
+ ]
+ },
+ {
+ "name": "inspect",
+ "parameters": [
+ { "name": "object", "$ref": "Runtime.RemoteObject" },
+ { "name": "hints", "type": "object" }
+ ]
+ },
+ {
+ "name": "detached",
+ "description": "Fired when remote debugging connection is about to be terminated. Contains detach reason.",
+ "parameters": [
+ { "name": "reason", "type": "string", "description": "The reason why connection has been terminated." }
+ ]
+ },
+ {
+ "name": "targetCrashed",
+ "description": "Fired when debugging target has crashed"
+ }
+ ]
+ },
+ {
+ "domain": "Memory",
+ "hidden": true,
+ "types": [
+ {
+ "id": "MemoryBlock",
+ "type": "object",
+ "properties": [
+ { "name": "size", "type": "number", "optional": true, "description": "Size of the block in bytes if available" },
+ { "name": "name", "type": "string", "description": "Unique name used to identify the component that allocated this block" },
+ { "name": "children", "type": "array", "optional": true, "items": { "$ref": "MemoryBlock" }}
+ ]
+ },
+ {
+ "id": "HeapSnapshotChunk",
+ "type": "object",
+ "properties": [
+ { "name": "strings", "type": "array", "items": { "type": "string" }, "description": "An array of strings that were found since last update." },
+ { "name": "nodes", "type": "array", "items": { "type": "integer" }, "description": "An array of nodes that were found since last update." },
+ { "name": "edges", "type": "array", "items": { "type": "integer" }, "description": "An array of edges that were found since last update." },
+ { "name": "baseToRealNodeId", "type": "array", "items": { "type": "integer" }, "description": "An array of integers for nodeId remapping. Even nodeId has to be mapped to the following odd nodeId." }
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "getDOMCounters",
+ "returns": [
+ { "name": "documents", "type": "integer" },
+ { "name": "nodes", "type": "integer" },
+ { "name": "jsEventListeners", "type": "integer" }
+ ]
+ }
+ ],
+ "events": [
+ {
+ "name": "addNativeSnapshotChunk",
+ "parameters": [
+ { "name": "chunk", "$ref": "HeapSnapshotChunk", "description": "A chunk of the serialized the snapshot." }
+ ]
+ }
+ ]
+ },
+ {
+ "domain": "Page",
+ "description": "Actions and events related to the inspected page belong to the page domain.",
+ "types": [
+ {
+ "id": "ResourceType",
+ "type": "string",
+ "enum": ["Document", "Stylesheet", "Image", "Font", "Script", "XHR", "WebSocket", "Other"],
+ "description": "Resource type as it was perceived by the rendering engine."
+ },
+ {
+ "id": "FrameId",
+ "type": "string",
+ "description": "Unique frame identifier."
+ },
+ {
+ "id": "Frame",
+ "type": "object",
+ "description": "Information about the Frame on the page.",
+ "properties": [
+ { "name": "id", "type": "string", "description": "Frame unique identifier." },
+ { "name": "parentId", "type": "string", "optional": true, "description": "Parent frame identifier." },
+ { "name": "loaderId", "$ref": "Network.LoaderId", "description": "Identifier of the loader associated with this frame." },
+ { "name": "name", "type": "string", "optional": true, "description": "Frame's name as specified in the tag." },
+ { "name": "url", "type": "string", "description": "Frame document's URL." },
+ { "name": "securityOrigin", "type": "string", "description": "Frame document's security origin." },
+ { "name": "mimeType", "type": "string", "description": "Frame document's mimeType as determined by the browser." }
+ ]
+ },
+ {
+ "id": "FrameResourceTree",
+ "type": "object",
+ "description": "Information about the Frame hierarchy along with their cached resources.",
+ "properties": [
+ { "name": "frame", "$ref": "Frame", "description": "Frame information for this tree item." },
+ { "name": "childFrames", "type": "array", "optional": true, "items": { "$ref": "FrameResourceTree" }, "description": "Child frames." },
+ { "name": "resources", "type": "array",
+ "items": {
+ "type": "object",
+ "properties": [
+ { "name": "url", "type": "string", "description": "Resource URL." },
+ { "name": "type", "$ref": "ResourceType", "description": "Type of this resource." },
+ { "name": "mimeType", "type": "string", "description": "Resource mimeType as determined by the browser." },
+ { "name": "failed", "type": "boolean", "optional": true, "description": "True if the resource failed to load." },
+ { "name": "canceled", "type": "boolean", "optional": true, "description": "True if the resource was canceled during loading." }
+ ]
+ },
+ "description": "Information about frame resources."
+ }
+ ],
+ "hidden": true
+ },
+ {
+ "id": "SearchMatch",
+ "type": "object",
+ "description": "Search match for resource.",
+ "properties": [
+ { "name": "lineNumber", "type": "number", "description": "Line number in resource content." },
+ { "name": "lineContent", "type": "string", "description": "Line with match content." }
+ ],
+ "hidden": true
+ },
+ {
+ "id": "SearchResult",
+ "type": "object",
+ "description": "Search result for resource.",
+ "properties": [
+ { "name": "url", "type": "string", "description": "Resource URL." },
+ { "name": "frameId", "$ref": "FrameId", "description": "Resource frame id." },
+ { "name": "matchesCount", "type": "number", "description": "Number of matches in the resource content." }
+ ],
+ "hidden": true
+ },
+ {
+ "id": "Cookie",
+ "type": "object",
+ "description": "Cookie object",
+ "properties": [
+ { "name": "name", "type": "string", "description": "Cookie name." },
+ { "name": "value", "type": "string", "description": "Cookie value." },
+ { "name": "domain", "type": "string", "description": "Cookie domain." },
+ { "name": "path", "type": "string", "description": "Cookie path." },
+ { "name": "expires", "type": "number", "description": "Cookie expires." },
+ { "name": "size", "type": "integer", "description": "Cookie size." },
+ { "name": "httpOnly", "type": "boolean", "description": "True if cookie is http-only." },
+ { "name": "secure", "type": "boolean", "description": "True if cookie is secure." },
+ { "name": "session", "type": "boolean", "description": "True in case of session cookie." }
+ ],
+ "hidden": true
+ },
+ {
+ "id": "ScriptIdentifier",
+ "type": "string",
+ "description": "Unique script identifier.",
+ "hidden": true
+ },
+ {
+ "id": "NavigationEntry",
+ "type": "object",
+ "description": "Navigation history entry.",
+ "properties": [
+ { "name": "id", "type": "integer", "description": "Unique id of the navigation history entry." },
+ { "name": "url", "type": "string", "description": "URL of the navigation history entry." },
+ { "name": "title", "type": "string", "description": "Title of the navigation history entry." }
+ ],
+ "hidden": true
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables page domain notifications."
+ },
+ {
+ "name": "disable",
+ "description": "Disables page domain notifications."
+ },
+ {
+ "name": "addScriptToEvaluateOnLoad",
+ "parameters": [
+ { "name": "scriptSource", "type": "string" }
+ ],
+ "returns": [
+ { "name": "identifier", "$ref": "ScriptIdentifier", "description": "Identifier of the added script." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "removeScriptToEvaluateOnLoad",
+ "parameters": [
+ { "name": "identifier", "$ref": "ScriptIdentifier" }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "reload",
+ "parameters": [
+ { "name": "ignoreCache", "type": "boolean", "optional": true, "description": "If true, browser cache is ignored (as if the user pressed Shift+refresh)." },
+ { "name": "scriptToEvaluateOnLoad", "type": "string", "optional": true, "description": "If set, the script will be injected into all frames of the inspected page after reload." },
+ { "name": "scriptPreprocessor", "type": "string", "optional": true, "description": "Script body that should evaluate to function that will preprocess all the scripts before their compilation.", "hidden": true }
+ ],
+ "description": "Reloads given page optionally ignoring the cache."
+ },
+ {
+ "name": "navigate",
+ "parameters": [
+ { "name": "url", "type": "string", "description": "URL to navigate the page to." }
+ ],
+ "description": "Navigates current page to the given URL."
+ },
+ {
+ "name": "getNavigationHistory",
+ "parameters": [],
+ "returns": [
+ { "name": "currentIndex", "type": "integer", "description": "Index of the current navigation history entry." },
+ { "name": "entries", "type": "array", "items": { "$ref": "NavigationEntry"}, "description": "Array of navigation history entries." }
+ ],
+ "description": "Returns navigation history for the current page.",
+ "hidden": true
+ },
+ {
+ "name": "navigateToHistoryEntry",
+ "parameters": [
+ { "name": "entryId", "type": "integer", "description": "Unique id of the entry to navigate to." }
+ ],
+ "description": "Navigates current page to the given history entry.",
+ "hidden": true
+ },
+ {
+ "name": "getCookies",
+ "returns": [
+ { "name": "cookies", "type": "array", "items": { "$ref": "Cookie"}, "description": "Array of cookie objects." },
+ { "name": "cookiesString", "type": "string", "description": "document.cookie string representation of the cookies." }
+ ],
+ "description": "Returns all browser cookies. Depending on the backend support, will either return detailed cookie information in the <code>cookie</code> field or string cookie representation using <code>cookieString</code>.",
+ "hidden": true
+ },
+ {
+ "name": "deleteCookie",
+ "parameters": [
+ { "name": "cookieName", "type": "string", "description": "Name of the cookie to remove." },
+ { "name": "url", "type": "string", "description": "URL to match cooke domain and path." }
+ ],
+ "description": "Deletes browser cookie with given name, domain and path.",
+ "hidden": true
+ },
+ {
+ "name": "getResourceTree",
+ "description": "Returns present frame / resource tree structure.",
+ "returns": [
+ { "name": "frameTree", "$ref": "FrameResourceTree", "description": "Present frame / resource tree structure." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "getResourceContent",
+ "description": "Returns content of the given resource.",
+ "parameters": [
+ { "name": "frameId", "$ref": "FrameId", "description": "Frame id to get resource for." },
+ { "name": "url", "type": "string", "description": "URL of the resource to get content for." }
+ ],
+ "returns": [
+ { "name": "content", "type": "string", "description": "Resource content." },
+ { "name": "base64Encoded", "type": "boolean", "description": "True, if content was served as base64." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "searchInResource",
+ "description": "Searches for given string in resource content.",
+ "parameters": [
+ { "name": "frameId", "$ref": "FrameId", "description": "Frame id for resource to search in." },
+ { "name": "url", "type": "string", "description": "URL of the resource to search in." },
+ { "name": "query", "type": "string", "description": "String to search for." },
+ { "name": "caseSensitive", "type": "boolean", "optional": true, "description": "If true, search is case sensitive." },
+ { "name": "isRegex", "type": "boolean", "optional": true, "description": "If true, treats string parameter as regex." }
+ ],
+ "returns": [
+ { "name": "result", "type": "array", "items": { "$ref": "SearchMatch" }, "description": "List of search matches." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "searchInResources",
+ "description": "Searches for given string in frame / resource tree structure.",
+ "parameters": [
+ { "name": "text", "type": "string", "description": "String to search for." },
+ { "name": "caseSensitive", "type": "boolean", "optional": true, "description": "If true, search is case sensitive." },
+ { "name": "isRegex", "type": "boolean", "optional": true, "description": "If true, treats string parameter as regex." }
+ ],
+ "returns": [
+ { "name": "result", "type": "array", "items": { "$ref": "SearchResult" }, "description": "List of search results." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "setDocumentContent",
+ "description": "Sets given markup as the document's HTML.",
+ "parameters": [
+ { "name": "frameId", "$ref": "FrameId", "description": "Frame id to set HTML for." },
+ { "name": "html", "type": "string", "description": "HTML content to set." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "setDeviceMetricsOverride",
+ "description": "Overrides the values of device screen dimensions (window.screen.width, window.screen.height, window.innerWidth, window.innerHeight, and \"device-width\"/\"device-height\"-related CSS media query results) and the font scale factor.",
+ "parameters": [
+ { "name": "width", "type": "integer", "description": "Overriding width value in pixels (minimum 0, maximum 10000000). 0 disables the override." },
+ { "name": "height", "type": "integer", "description": "Overriding height value in pixels (minimum 0, maximum 10000000). 0 disables the override." },
+ { "name": "fontScaleFactor", "type": "number", "description": "Overriding font scale factor value (must be positive). 1 disables the override." },
+ { "name": "fitWindow", "type": "boolean", "description": "Whether a view that exceeds the available browser window area should be scaled down to fit." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "setShowPaintRects",
+ "description": "Requests that backend shows paint rectangles",
+ "parameters": [
+ { "name": "result", "type": "boolean", "description": "True for showing paint rectangles" }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "setShowDebugBorders",
+ "description": "Requests that backend shows debug borders on layers",
+ "parameters": [
+ { "name": "show", "type": "boolean", "description": "True for showing debug borders" }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "setShowFPSCounter",
+ "description": "Requests that backend shows the FPS counter",
+ "parameters": [
+ { "name": "show", "type": "boolean", "description": "True for showing the FPS counter" }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "setContinuousPaintingEnabled",
+ "description": "Requests that backend enables continuous painting",
+ "parameters": [
+ { "name": "enabled", "type": "boolean", "description": "True for enabling cointinuous painting" }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "setShowScrollBottleneckRects",
+ "description": "Requests that backend shows scroll bottleneck rects",
+ "parameters": [
+ { "name": "show", "type": "boolean", "description": "True for showing scroll bottleneck rects" }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "getScriptExecutionStatus",
+ "description": "Determines if scripts can be executed in the page.",
+ "returns": [
+ { "name": "result", "type": "string", "enum": ["allowed", "disabled", "forbidden"], "description": "Script execution status: \"allowed\" if scripts can be executed, \"disabled\" if script execution has been disabled through page settings, \"forbidden\" if script execution for the given page is not possible for other reasons." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "setScriptExecutionDisabled",
+ "description": "Switches script execution in the page.",
+ "parameters": [
+ { "name": "value", "type": "boolean", "description": "Whether script execution should be disabled in the page." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "setGeolocationOverride",
+ "description": "Overrides the Geolocation Position or Error.",
+ "parameters": [
+ { "name": "latitude", "type": "number", "optional": true, "description": "Mock longitude"},
+ { "name": "longitude", "type": "number", "optional": true, "description": "Mock latitude"},
+ { "name": "accuracy", "type": "number", "optional": true, "description": "Mock accuracy"}
+ ]
+ },
+ {
+ "name": "clearGeolocationOverride",
+ "description": "Clears the overriden Geolocation Position and Error."
+ },
+ {
+ "name": "setDeviceOrientationOverride",
+ "description": "Overrides the Device Orientation.",
+ "parameters": [
+ { "name": "alpha", "type": "number", "description": "Mock alpha"},
+ { "name": "beta", "type": "number", "description": "Mock beta"},
+ { "name": "gamma", "type": "number", "description": "Mock gamma"}
+ ],
+ "hidden": true
+ },
+ {
+ "name": "clearDeviceOrientationOverride",
+ "description": "Clears the overridden Device Orientation.",
+ "hidden": true
+ },
+ {
+ "name": "setTouchEmulationEnabled",
+ "parameters": [
+ { "name": "enabled", "type": "boolean", "description": "Whether the touch event emulation should be enabled." }
+ ],
+ "description": "Toggles mouse event-based touch event emulation.",
+ "hidden": true
+ },
+ {
+ "name": "setEmulatedMedia",
+ "parameters": [
+ { "name": "media", "type": "string", "description": "Media type to emulate. Empty string disables the override." }
+ ],
+ "description": "Emulates the given media for CSS media queries.",
+ "hidden": true
+ },
+ {
+ "name": "captureScreenshot",
+ "description": "Capture page screenshot.",
+ "parameters": [
+ { "name": "format", "type": "string", "optional": true, "enum": ["jpeg", "png"], "description": "Image compression format." },
+ { "name": "quality", "type": "integer", "hidden": true, "optional": true, "description": "Compression quality from range [0..100]." },
+ { "name": "maxWidth", "type": "integer", "hidden": true, "optional": true, "description": "Maximum screenshot width." },
+ { "name": "maxHeight", "type": "integer", "hidden": true, "optional": true, "description": "Maximum screenshot height." }
+ ],
+ "returns": [
+ { "name": "data", "type": "string", "description": "Base64-encoded image data (PNG)." },
+ { "name": "deviceScaleFactor", "type": "number", "hidden": true, "description": "Device scale factor." },
+ { "name": "pageScaleFactor", "type": "number", "hidden": true, "description": "Page scale factor." },
+ { "name": "viewport", "$ref": "DOM.Rect", "hidden": true, "description": "Viewport in CSS pixels." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "startScreencast",
+ "description": "Starts sending each frame using the <code>screencastFrame</code> event.",
+ "parameters": [
+ { "name": "format", "type": "string", "optional": true, "enum": ["jpeg", "png"], "description": "Image compression format." },
+ { "name": "quality", "type": "integer", "optional": true, "description": "Compression quality from range [0..100]." },
+ { "name": "maxWidth", "type": "integer", "optional": true, "description": "Maximum screenshot width." },
+ { "name": "maxHeight", "type": "integer", "optional": true, "description": "Maximum screenshot height." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "stopScreencast",
+ "description": "Stops sending each frame in the <code>screencastFrame</code>.",
+ "hidden": true
+ },
+ {
+ "name": "handleJavaScriptDialog",
+ "description": "Accepts or dismisses a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload).",
+ "parameters": [
+ { "name": "accept", "type": "boolean", "description": "Whether to accept or dismiss the dialog." },
+ { "name": "promptText", "type": "string", "optional": true, "description": "The text to enter into the dialog prompt before accepting. Used only if this is a prompt dialog." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "setShowViewportSizeOnResize",
+ "description": "Paints viewport size upon main frame resize.",
+ "parameters": [
+ { "name": "show", "type": "boolean", "description": "Whether to paint size or not." },
+ { "name": "showGrid", "type": "boolean", "optional": true, "description": "Whether to paint grid as well." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "setForceCompositingMode",
+ "description": "Force accelerated compositing mode for inspected page.",
+ "parameters": [
+ { "name": "force", "type": "boolean", "description": "Whether to force accelerated compositing or not." }
+ ],
+ "hidden": true
+ }
+ ],
+ "events": [
+ {
+ "name": "domContentEventFired",
+ "parameters": [
+ { "name": "timestamp", "type": "number" }
+ ]
+ },
+ {
+ "name": "loadEventFired",
+ "parameters": [
+ { "name": "timestamp", "type": "number" }
+ ]
+ },
+ {
+ "name": "frameAttached",
+ "description": "Fired when frame has been attached to its parent.",
+ "parameters": [
+ { "name": "frameId", "$ref": "FrameId", "description": "Id of the frame that has been attached." }
+ ]
+ },
+ {
+ "name": "frameNavigated",
+ "description": "Fired once navigation of the frame has completed. Frame is now associated with the new loader.",
+ "parameters": [
+ { "name": "frame", "$ref": "Frame", "description": "Frame object." }
+ ]
+ },
+ {
+ "name": "frameDetached",
+ "description": "Fired when frame has been detached from its parent.",
+ "parameters": [
+ { "name": "frameId", "$ref": "FrameId", "description": "Id of the frame that has been detached." }
+ ]
+ },
+ {
+ "name": "frameStartedLoading",
+ "description": "Fired when frame has started loading.",
+ "parameters": [
+ { "name": "frameId", "$ref": "FrameId", "description": "Id of the frame that has started loading." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "frameStoppedLoading",
+ "description": "Fired when frame has stopped loading.",
+ "parameters": [
+ { "name": "frameId", "$ref": "FrameId", "description": "Id of the frame that has stopped loading." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "frameScheduledNavigation",
+ "description": "Fired when frame schedules a potential navigation.",
+ "parameters": [
+ { "name": "frameId", "$ref": "FrameId", "description": "Id of the frame that has scheduled a navigation." },
+ { "name": "delay", "type": "number", "description": "Delay (in seconds) until the navigation is scheduled to begin. The navigation is not guaranteed to start." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "frameClearedScheduledNavigation",
+ "description": "Fired when frame no longer has a scheduled navigation.",
+ "parameters": [
+ { "name": "frameId", "$ref": "FrameId", "description": "Id of the frame that has cleared its scheduled navigation." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "javascriptDialogOpening",
+ "description": "Fired when a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload) is about to open.",
+ "parameters": [
+ { "name": "message", "type": "string", "description": "Message that will be displayed by the dialog." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "javascriptDialogClosed",
+ "description": "Fired when a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload) has been closed.",
+ "hidden": true
+ },
+ {
+ "name": "scriptsEnabled",
+ "description": "Fired when the JavaScript is enabled/disabled on the page",
+ "parameters": [
+ { "name": "isEnabled", "type": "boolean", "description": "Whether script execution is enabled or disabled on the page." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "screencastFrame",
+ "description": "Compressed image data requested by the <code>startScreencast</code>.",
+ "parameters": [
+ { "name": "data", "type": "string", "description": "Base64-encoded compressed image." },
+ { "name": "deviceScaleFactor", "type": "number", "hidden": true, "optional": true, "description": "Device scale factor." },
+ { "name": "pageScaleFactor", "type": "number", "hidden": true, "optional": true, "description": "Page scale factor." },
+ { "name": "viewport", "$ref": "DOM.Rect", "hidden": true, "optional": true, "description": "Viewport in CSS pixels." },
+ { "name": "offsetTop", "type": "number", "hidden": true, "optional": true, "description": "Top offset in DIP." },
+ { "name": "offsetBottom", "type": "number", "hidden": true, "optional": true, "description": "Bottom offset in DIP." }
+ ],
+ "hidden": true
+ }
+ ]
+ },
+ {
+ "domain": "Runtime",
+ "description": "Runtime domain exposes JavaScript runtime by means of remote evaluation and mirror objects. Evaluation results are returned as mirror object that expose object type, string representation and unique identifier that can be used for further object reference. Original objects are maintained in memory unless they are either explicitly released or are released along with the other objects in their object group.",
+ "types": [
+ {
+ "id": "RemoteObjectId",
+ "type": "string",
+ "description": "Unique object identifier."
+ },
+ {
+ "id": "RemoteObject",
+ "type": "object",
+ "description": "Mirror object referencing original JavaScript object.",
+ "properties": [
+ { "name": "type", "type": "string", "enum": ["object", "function", "undefined", "string", "number", "boolean"], "description": "Object type." },
+ { "name": "subtype", "type": "string", "optional": true, "enum": ["array", "null", "node", "regexp", "date"], "description": "Object subtype hint. Specified for <code>object</code> type values only." },
+ { "name": "className", "type": "string", "optional": true, "description": "Object class (constructor) name. Specified for <code>object</code> type values only." },
+ { "name": "value", "type": "any", "optional": true, "description": "Remote object value (in case of primitive values or JSON values if it was requested)." },
+ { "name": "description", "type": "string", "optional": true, "description": "String representation of the object." },
+ { "name": "objectId", "$ref": "RemoteObjectId", "optional": true, "description": "Unique object identifier (for non-primitive values)." },
+ { "name": "preview", "$ref": "ObjectPreview", "optional": true, "description": "Preview containing abbreviated property values.", "hidden": true }
+ ]
+ },
+ {
+ "id": "ObjectPreview",
+ "type": "object",
+ "hidden": true,
+ "description": "Object containing abbreviated remote object value.",
+ "properties": [
+ { "name": "lossless", "type": "boolean", "description": "Determines whether preview is lossless (contains all information of the original object)." },
+ { "name": "overflow", "type": "boolean", "description": "True iff some of the properties of the original did not fit." },
+ { "name": "properties", "type": "array", "items": { "$ref": "PropertyPreview" }, "description": "List of the properties." }
+ ]
+ },
+ {
+ "id": "PropertyPreview",
+ "type": "object",
+ "hidden": true,
+ "properties": [
+ { "name": "name", "type": "string", "description": "Property name." },
+ { "name": "type", "type": "string", "enum": ["object", "function", "undefined", "string", "number", "boolean"], "description": "Object type." },
+ { "name": "value", "type": "string", "optional": true, "description": "User-friendly property value string." },
+ { "name": "valuePreview", "$ref": "ObjectPreview", "optional": true, "description": "Nested value preview." },
+ { "name": "subtype", "type": "string", "optional": true, "enum": ["array", "null", "node", "regexp", "date"], "description": "Object subtype hint. Specified for <code>object</code> type values only." }
+ ]
+ },
+ {
+ "id": "PropertyDescriptor",
+ "type": "object",
+ "description": "Object property descriptor.",
+ "properties": [
+ { "name": "name", "type": "string", "description": "Property name." },
+ { "name": "value", "$ref": "RemoteObject", "optional": true, "description": "The value associated with the property." },
+ { "name": "writable", "type": "boolean", "optional": true, "description": "True if the value associated with the property may be changed (data descriptors only)." },
+ { "name": "get", "$ref": "RemoteObject", "optional": true, "description": "A function which serves as a getter for the property, or <code>undefined</code> if there is no getter (accessor descriptors only)." },
+ { "name": "set", "$ref": "RemoteObject", "optional": true, "description": "A function which serves as a setter for the property, or <code>undefined</code> if there is no setter (accessor descriptors only)." },
+ { "name": "configurable", "type": "boolean", "description": "True if the type of this property descriptor may be changed and if the property may be deleted from the corresponding object." },
+ { "name": "enumerable", "type": "boolean", "description": "True if this property shows up during enumeration of the properties on the corresponding object." },
+ { "name": "wasThrown", "type": "boolean", "optional": true, "description": "True if the result was thrown during the evaluation." },
+ { "name": "isOwn", "optional": true, "type": "boolean", "description": "True if the property is owned for the object.", "hidden": true }
+
+ ]
+ },
+ {
+ "id": "InternalPropertyDescriptor",
+ "type": "object",
+ "description": "Object internal property descriptor. This property isn't normally visible in JavaScript code.",
+ "properties": [
+ { "name": "name", "type": "string", "description": "Conventional property name." },
+ { "name": "value", "$ref": "RemoteObject", "optional": true, "description": "The value associated with the property." }
+ ],
+ "hidden": true
+ },
+ {
+ "id": "CallArgument",
+ "type": "object",
+ "description": "Represents function call argument. Either remote object id <code>objectId</code> or primitive <code>value</code> or neither of (for undefined) them should be specified.",
+ "properties": [
+ { "name": "value", "type": "any", "optional": true, "description": "Primitive value." },
+ { "name": "objectId", "$ref": "RemoteObjectId", "optional": true, "description": "Remote object handle." }
+ ]
+ },
+ {
+ "id": "ExecutionContextId",
+ "type": "integer",
+ "description": "Id of an execution context."
+ },
+ {
+ "id": "ExecutionContextDescription",
+ "type": "object",
+ "description": "Description of an isolated world.",
+ "properties": [
+ { "name": "id", "$ref": "ExecutionContextId", "description": "Unique id of the execution context. It can be used to specify in which execution context script evaluation should be performed." },
+ { "name": "isPageContext", "type": "boolean", "description": "True if this is a context where inpspected web page scripts run. False if it is a content script isolated context.", "hidden": true },
+ { "name": "name", "type": "string", "description": "Human readable name describing given context.", "hidden": true},
+ { "name": "frameId", "$ref": "Page.FrameId", "description": "Id of the owning frame." }
+ ]
+ }
+
+ ],
+ "commands": [
+ {
+ "name": "evaluate",
+ "parameters": [
+ { "name": "expression", "type": "string", "description": "Expression to evaluate." },
+ { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." },
+ { "name": "includeCommandLineAPI", "type": "boolean", "optional": true, "description": "Determines whether Command Line API should be available during the evaluation.", "hidden": true },
+ { "name": "doNotPauseOnExceptionsAndMuteConsole", "type": "boolean", "optional": true, "description": "Specifies whether evaluation should stop on exceptions and mute console. Overrides setPauseOnException state.", "hidden": true },
+ { "name": "contextId", "$ref": "Runtime.ExecutionContextId", "optional": true, "description": "Specifies in which isolated context to perform evaluation. Each content script lives in an isolated context and this parameter may be used to specify one of those contexts. If the parameter is omitted or 0 the evaluation will be performed in the context of the inspected page." },
+ { "name": "returnByValue", "type": "boolean", "optional": true, "description": "Whether the result is expected to be a JSON object that should be sent by value." },
+ { "name": "generatePreview", "type": "boolean", "optional": true, "hidden": true, "description": "Whether preview should be generated for the result." }
+ ],
+ "returns": [
+ { "name": "result", "$ref": "RemoteObject", "description": "Evaluation result." },
+ { "name": "wasThrown", "type": "boolean", "optional": true, "description": "True if the result was thrown during the evaluation." }
+ ],
+ "description": "Evaluates expression on global object."
+ },
+ {
+ "name": "callFunctionOn",
+ "parameters": [
+ { "name": "objectId", "$ref": "RemoteObjectId", "description": "Identifier of the object to call function on." },
+ { "name": "functionDeclaration", "type": "string", "description": "Declaration of the function to call." },
+ { "name": "arguments", "type": "array", "items": { "$ref": "CallArgument", "description": "Call argument." }, "optional": true, "description": "Call arguments. All call arguments must belong to the same JavaScript world as the target object." },
+ { "name": "doNotPauseOnExceptionsAndMuteConsole", "type": "boolean", "optional": true, "description": "Specifies whether function call should stop on exceptions and mute console. Overrides setPauseOnException state.", "hidden": true },
+ { "name": "returnByValue", "type": "boolean", "optional": true, "description": "Whether the result is expected to be a JSON object which should be sent by value." },
+ { "name": "generatePreview", "type": "boolean", "optional": true, "hidden": true, "description": "Whether preview should be generated for the result." }
+ ],
+ "returns": [
+ { "name": "result", "$ref": "RemoteObject", "description": "Call result." },
+ { "name": "wasThrown", "type": "boolean", "optional": true, "description": "True if the result was thrown during the evaluation." }
+ ],
+ "description": "Calls function with given declaration on the given object. Object group of the result is inherited from the target object."
+ },
+ {
+ "name": "getProperties",
+ "parameters": [
+ { "name": "objectId", "$ref": "RemoteObjectId", "description": "Identifier of the object to return properties for." },
+ { "name": "ownProperties", "optional": true, "type": "boolean", "description": "If true, returns properties belonging only to the element itself, not to its prototype chain." },
+ { "name": "accessorPropertiesOnly", "optional": true, "type": "boolean", "description": "If true, returns accessor properties (with getter/setter) only; internal properties are not returned either.", "hidden": true }
+ ],
+ "returns": [
+ { "name": "result", "type": "array", "items": { "$ref": "PropertyDescriptor"}, "description": "Object properties." },
+ { "name": "internalProperties", "optional": true, "type": "array", "items": { "$ref": "InternalPropertyDescriptor"}, "description": "Internal object properties (only of the element itself).", "hidden": true }
+ ],
+ "description": "Returns properties of a given object. Object group of the result is inherited from the target object."
+ },
+ {
+ "name": "releaseObject",
+ "parameters": [
+ { "name": "objectId", "$ref": "RemoteObjectId", "description": "Identifier of the object to release." }
+ ],
+ "description": "Releases remote object with given id."
+ },
+ {
+ "name": "releaseObjectGroup",
+ "parameters": [
+ { "name": "objectGroup", "type": "string", "description": "Symbolic object group name." }
+ ],
+ "description": "Releases all remote objects that belong to a given group."
+ },
+ {
+ "name": "run",
+ "hidden": true,
+ "description": "Tells inspected instance(worker or page) that it can run in case it was started paused."
+ },
+ {
+ "name": "enable",
+ "description": "Enables reporting of execution contexts creation by means of <code>executionContextCreated</code> event. When the reporting gets enabled the event will be sent immediately for each existing execution context."
+ },
+ {
+ "name": "disable",
+ "hidden": true,
+ "description": "Disables reporting of execution contexts creation."
+ }
+ ],
+ "events": [
+ {
+ "name": "executionContextCreated",
+ "parameters": [
+ { "name": "context", "$ref": "ExecutionContextDescription", "description": "A newly created execution contex." }
+ ],
+ "description": "Issued when new execution context is created."
+ }
+ ]
+ },
+ {
+ "domain": "Console",
+ "description": "Console domain defines methods and events for interaction with the JavaScript console. Console collects messages created by means of the <a href='http://getfirebug.com/wiki/index.php/Console_API'>JavaScript Console API</a>. One needs to enable this domain using <code>enable</code> command in order to start receiving the console messages. Browser collects messages issued while console domain is not enabled as well and reports them using <code>messageAdded</code> notification upon enabling.",
+ "types": [
+ {
+ "id": "Timestamp",
+ "type": "number",
+ "description": "Number of seconds since epoch.",
+ "hidden": true
+ },
+ {
+ "id": "ConsoleMessage",
+ "type": "object",
+ "description": "Console message.",
+ "properties": [
+ { "name": "source", "type": "string", "enum": ["xml", "javascript", "network", "console-api", "storage", "appcache", "rendering", "css", "security", "other", "deprecation"], "description": "Message source." },
+ { "name": "level", "type": "string", "enum": ["log", "warning", "error", "debug"], "description": "Message severity." },
+ { "name": "text", "type": "string", "description": "Message text." },
+ { "name": "type", "type": "string", "optional": true, "enum": ["log", "dir", "dirxml", "table", "trace", "clear", "startGroup", "startGroupCollapsed", "endGroup", "assert", "timing", "profile", "profileEnd"], "description": "Console message type." },
+ { "name": "url", "type": "string", "optional": true, "description": "URL of the message origin." },
+ { "name": "line", "type": "integer", "optional": true, "description": "Line number in the resource that generated this message." },
+ { "name": "column", "type": "integer", "optional": true, "description": "Column number in the resource that generated this message." },
+ { "name": "repeatCount", "type": "integer", "optional": true, "description": "Repeat count for repeated messages." },
+ { "name": "parameters", "type": "array", "items": { "$ref": "Runtime.RemoteObject" }, "optional": true, "description": "Message parameters in case of the formatted message." },
+ { "name": "stackTrace", "$ref": "StackTrace", "optional": true, "description": "JavaScript stack trace for assertions and error messages." },
+ { "name": "networkRequestId", "$ref": "Network.RequestId", "optional": true, "description": "Identifier of the network request associated with this message." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp, when this message was fired.", "hidden": true }
+ ]
+ },
+ {
+ "id": "CallFrame",
+ "type": "object",
+ "description": "Stack entry for console errors and assertions.",
+ "properties": [
+ { "name": "functionName", "type": "string", "description": "JavaScript function name." },
+ { "name": "scriptId", "type": "string", "description": "JavaScript script id." },
+ { "name": "url", "type": "string", "description": "JavaScript script name or url." },
+ { "name": "lineNumber", "type": "integer", "description": "JavaScript script line number." },
+ { "name": "columnNumber", "type": "integer", "description": "JavaScript script column number." }
+ ]
+ },
+ {
+ "id": "StackTrace",
+ "type": "array",
+ "items": { "$ref": "CallFrame" },
+ "description": "Call frames for assertions or error messages."
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables console domain, sends the messages collected so far to the client by means of the <code>messageAdded</code> notification."
+ },
+ {
+ "name": "disable",
+ "description": "Disables console domain, prevents further console messages from being reported to the client."
+ },
+ {
+ "name": "clearMessages",
+ "description": "Clears console messages collected in the browser."
+ },
+ {
+ "name": "setMonitoringXHREnabled",
+ "parameters": [
+ { "name": "enabled", "type": "boolean", "description": "Monitoring enabled state." }
+ ],
+ "description": "Toggles monitoring of XMLHttpRequest. If <code>true</code>, console will receive messages upon each XHR issued.",
+ "hidden": true
+ },
+ {
+ "name": "addInspectedNode",
+ "parameters": [
+ { "name": "nodeId", "$ref": "DOM.NodeId", "description": "DOM node id to be accessible by means of $x command line API." }
+ ],
+ "description": "Enables console to refer to the node with given id via $x (see Command Line API for more details $x functions).",
+ "hidden": true
+ },
+ {
+ "name": "addInspectedHeapObject",
+ "parameters": [
+ { "name": "heapObjectId", "type": "integer" }
+ ],
+ "hidden": true
+ }
+ ],
+ "events": [
+ {
+ "name": "messageAdded",
+ "parameters": [
+ { "name": "message", "$ref": "ConsoleMessage", "description": "Console message that has been added." }
+ ],
+ "description": "Issued when new console message is added."
+ },
+ {
+ "name": "messageRepeatCountUpdated",
+ "parameters": [
+ { "name": "count", "type": "integer", "description": "New repeat count value." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp of most recent message in batch.", "hidden": true }
+ ],
+ "description": "Issued when subsequent message(s) are equal to the previous one(s)."
+ },
+ {
+ "name": "messagesCleared",
+ "description": "Issued when console is cleared. This happens either upon <code>clearMessages</code> command or after page navigation."
+ }
+ ]
+ },
+ {
+ "domain": "Network",
+ "description": "Network domain allows tracking network activities of the page. It exposes information about http, file, data and other requests and responses, their headers, bodies, timing, etc.",
+ "types": [
+ {
+ "id": "LoaderId",
+ "type": "string",
+ "description": "Unique loader identifier."
+ },
+ {
+ "id": "RequestId",
+ "type": "string",
+ "description": "Unique request identifier."
+ },
+ {
+ "id": "Timestamp",
+ "type": "number",
+ "description": "Number of seconds since epoch."
+ },
+ {
+ "id": "Headers",
+ "type": "object",
+ "description": "Request / response headers as keys / values of JSON object."
+ },
+ {
+ "id": "ResourceTiming",
+ "type": "object",
+ "description": "Timing information for the request.",
+ "properties": [
+ { "name": "requestTime", "type": "number", "description": "Timing's requestTime is a baseline in seconds, while the other numbers are ticks in milliseconds relatively to this requestTime." },
+ { "name": "proxyStart", "type": "number", "description": "Started resolving proxy." },
+ { "name": "proxyEnd", "type": "number", "description": "Finished resolving proxy." },
+ { "name": "dnsStart", "type": "number", "description": "Started DNS address resolve." },
+ { "name": "dnsEnd", "type": "number", "description": "Finished DNS address resolve." },
+ { "name": "connectStart", "type": "number", "description": "Started connecting to the remote host." },
+ { "name": "connectEnd", "type": "number", "description": "Connected to the remote host." },
+ { "name": "sslStart", "type": "number", "description": "Started SSL handshake." },
+ { "name": "sslEnd", "type": "number", "description": "Finished SSL handshake." },
+ { "name": "sendStart", "type": "number", "description": "Started sending request." },
+ { "name": "sendEnd", "type": "number", "description": "Finished sending request." },
+ { "name": "receiveHeadersEnd", "type": "number", "description": "Finished receiving response headers." }
+ ]
+ },
+ {
+ "id": "Request",
+ "type": "object",
+ "description": "HTTP request data.",
+ "properties": [
+ { "name": "url", "type": "string", "description": "Request URL." },
+ { "name": "method", "type": "string", "description": "HTTP request method." },
+ { "name": "headers", "$ref": "Headers", "description": "HTTP request headers." },
+ { "name": "postData", "type": "string", "optional": true, "description": "HTTP POST request data." }
+ ]
+ },
+ {
+ "id": "Response",
+ "type": "object",
+ "description": "HTTP response data.",
+ "properties": [
+ { "name": "url", "type": "string", "description": "Response URL. This URL can be different from CachedResource.url in case of redirect." },
+ { "name": "status", "type": "number", "description": "HTTP response status code." },
+ { "name": "statusText", "type": "string", "description": "HTTP response status text." },
+ { "name": "headers", "$ref": "Headers", "description": "HTTP response headers." },
+ { "name": "headersText", "type": "string", "optional": true, "description": "HTTP response headers text." },
+ { "name": "mimeType", "type": "string", "description": "Resource mimeType as determined by the browser." },
+ { "name": "requestHeaders", "$ref": "Headers", "optional": true, "description": "Refined HTTP request headers that were actually transmitted over the network." },
+ { "name": "requestHeadersText", "type": "string", "optional": true, "description": "HTTP request headers text." },
+ { "name": "connectionReused", "type": "boolean", "description": "Specifies whether physical connection was actually reused for this request." },
+ { "name": "connectionId", "type": "number", "description": "Physical connection id that was actually used for this request." },
+ { "name": "fromDiskCache", "type": "boolean", "optional": true, "description": "Specifies that the request was served from the disk cache." },
+ { "name": "timing", "$ref": "ResourceTiming", "optional": true, "description": "Timing information for the given request." }
+ ]
+ },
+ {
+ "id": "WebSocketRequest",
+ "type": "object",
+ "description": "WebSocket request data.",
+ "hidden": true,
+ "properties": [
+ { "name": "headers", "$ref": "Headers", "description": "HTTP response headers." }
+ ]
+ },
+ {
+ "id": "WebSocketResponse",
+ "type": "object",
+ "description": "WebSocket response data.",
+ "hidden": true,
+ "properties": [
+ { "name": "status", "type": "number", "description": "HTTP response status code." },
+ { "name": "statusText", "type": "string", "description": "HTTP response status text." },
+ { "name": "headers", "$ref": "Headers", "description": "HTTP response headers." }
+ ]
+ },
+ {
+ "id": "WebSocketFrame",
+ "type": "object",
+ "description": "WebSocket frame data.",
+ "hidden": true,
+ "properties": [
+ { "name": "opcode", "type": "number", "description": "WebSocket frame opcode." },
+ { "name": "mask", "type": "boolean", "description": "WebSocke frame mask." },
+ { "name": "payloadData", "type": "string", "description": "WebSocke frame payload data." }
+ ]
+ },
+ {
+ "id": "CachedResource",
+ "type": "object",
+ "description": "Information about the cached resource.",
+ "properties": [
+ { "name": "url", "type": "string", "description": "Resource URL. This is the url of the original network request." },
+ { "name": "type", "$ref": "Page.ResourceType", "description": "Type of this resource." },
+ { "name": "response", "$ref": "Response", "optional": true, "description": "Cached response data." },
+ { "name": "bodySize", "type": "number", "description": "Cached response body size." }
+ ]
+ },
+ {
+ "id": "Initiator",
+ "type": "object",
+ "description": "Information about the request initiator.",
+ "properties": [
+ { "name": "type", "type": "string", "enum": ["parser", "script", "other"], "description": "Type of this initiator." },
+ { "name": "stackTrace", "$ref": "Console.StackTrace", "optional": true, "description": "Initiator JavaScript stack trace, set for Script only." },
+ { "name": "url", "type": "string", "optional": true, "description": "Initiator URL, set for Parser type only." },
+ { "name": "lineNumber", "type": "number", "optional": true, "description": "Initiator line number, set for Parser type only." }
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables network tracking, network events will now be delivered to the client."
+ },
+ {
+ "name": "disable",
+ "description": "Disables network tracking, prevents network events from being sent to the client."
+ },
+ {
+ "name": "setUserAgentOverride",
+ "description": "Allows overriding user agent with the given string.",
+ "parameters": [
+ { "name": "userAgent", "type": "string", "description": "User agent to use." }
+ ]
+ },
+ {
+ "name": "setExtraHTTPHeaders",
+ "description": "Specifies whether to always send extra HTTP headers with the requests from this page.",
+ "parameters": [
+ { "name": "headers", "$ref": "Headers", "description": "Map with extra HTTP headers." }
+ ]
+ },
+ {
+ "name": "getResponseBody",
+ "description": "Returns content served for the given request.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Identifier of the network request to get content for." }
+ ],
+ "returns": [
+ { "name": "body", "type": "string", "description": "Response body." },
+ { "name": "base64Encoded", "type": "boolean", "description": "True, if content was sent as base64." }
+ ]
+ },
+ {
+ "name": "replayXHR",
+ "description": "This method sends a new XMLHttpRequest which is identical to the original one. The following parameters should be identical: method, url, async, request body, extra headers, withCredentials attribute, user, password.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Identifier of XHR to replay." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "canClearBrowserCache",
+ "description": "Tells whether clearing browser cache is supported.",
+ "returns": [
+ { "name": "result", "type": "boolean", "description": "True if browser cache can be cleared." }
+ ]
+ },
+ {
+ "name": "clearBrowserCache",
+ "description": "Clears browser cache."
+ },
+ {
+ "name": "canClearBrowserCookies",
+ "description": "Tells whether clearing browser cookies is supported.",
+ "returns": [
+ { "name": "result", "type": "boolean", "description": "True if browser cookies can be cleared." }
+ ]
+ },
+ {
+ "name": "clearBrowserCookies",
+ "description": "Clears browser cookies."
+ },
+ {
+ "name": "setCacheDisabled",
+ "parameters": [
+ { "name": "cacheDisabled", "type": "boolean", "description": "Cache disabled state." }
+ ],
+ "description": "Toggles ignoring cache for each request. If <code>true</code>, cache will not be used."
+ },
+ {
+ "name": "loadResourceForFrontend",
+ "async": true,
+ "parameters": [
+ { "name": "frameId", "$ref": "Page.FrameId", "description": "Frame to load the resource from." },
+ { "name": "url", "type": "string", "description": "URL of the resource to load." },
+ { "name": "requestHeaders", "$ref": "Network.Headers", "optional": true, "description": "Request headers." }
+ ],
+ "returns": [
+ { "name": "statusCode", "type": "number", "description": "HTTP status code." },
+ { "name": "responseHeaders", "$ref": "Network.Headers", "description": "Response headers." },
+ { "name": "content", "type": "string", "description": "Resource content." }
+ ],
+ "description": "Loads a resource in the context of a frame on the inspected page without cross origin checks.",
+ "hidden": true
+ }
+ ],
+ "events": [
+ {
+ "name": "requestWillBeSent",
+ "description": "Fired when page is about to send HTTP request.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "frameId", "$ref": "Page.FrameId", "description": "Frame identifier.", "hidden": true },
+ { "name": "loaderId", "$ref": "LoaderId", "description": "Loader identifier." },
+ { "name": "documentURL", "type": "string", "description": "URL of the document this request is loaded for." },
+ { "name": "request", "$ref": "Request", "description": "Request data." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
+ { "name": "initiator", "$ref": "Initiator", "description": "Request initiator." },
+ { "name": "redirectResponse", "optional": true, "$ref": "Response", "description": "Redirect response data." }
+ ]
+ },
+ {
+ "name": "requestServedFromCache",
+ "description": "Fired if request ended up loading from cache.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." }
+ ]
+ },
+ {
+ "name": "responseReceived",
+ "description": "Fired when HTTP response is available.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "frameId", "$ref": "Page.FrameId", "description": "Frame identifier.", "hidden": true },
+ { "name": "loaderId", "$ref": "LoaderId", "description": "Loader identifier." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
+ { "name": "type", "$ref": "Page.ResourceType", "description": "Resource type." },
+ { "name": "response", "$ref": "Response", "description": "Response data." }
+ ]
+ },
+ {
+ "name": "dataReceived",
+ "description": "Fired when data chunk was received over the network.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
+ { "name": "dataLength", "type": "integer", "description": "Data chunk length." },
+ { "name": "encodedDataLength", "type": "integer", "description": "Actual bytes received (might be less than dataLength for compressed encodings)." }
+ ]
+ },
+ {
+ "name": "loadingFinished",
+ "description": "Fired when HTTP request has finished loading.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." }
+ ]
+ },
+ {
+ "name": "loadingFailed",
+ "description": "Fired when HTTP request has failed to load.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
+ { "name": "errorText", "type": "string", "description": "User friendly error message." },
+ { "name": "canceled", "type": "boolean", "optional": true, "description": "True if loading was canceled." }
+ ]
+ },
+ {
+ "name": "webSocketWillSendHandshakeRequest",
+ "description": "Fired when WebSocket is about to initiate handshake.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
+ { "name": "request", "$ref": "WebSocketRequest", "description": "WebSocket request data." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "webSocketHandshakeResponseReceived",
+ "description": "Fired when WebSocket handshake response becomes available.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
+ { "name": "response", "$ref": "WebSocketResponse", "description": "WebSocket response data." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "webSocketCreated",
+ "description": "Fired upon WebSocket creation.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "url", "type": "string", "description": "WebSocket request URL." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "webSocketClosed",
+ "description": "Fired when WebSocket is closed.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "webSocketFrameReceived",
+ "description": "Fired when WebSocket frame is received.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
+ { "name": "response", "$ref": "WebSocketFrame", "description": "WebSocket response data." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "webSocketFrameError",
+ "description": "Fired when WebSocket frame error occurs.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
+ { "name": "errorMessage", "type": "string", "description": "WebSocket frame error message." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "webSocketFrameSent",
+ "description": "Fired when WebSocket frame is sent.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
+ { "name": "response", "$ref": "WebSocketFrame", "description": "WebSocket response data." }
+ ],
+ "hidden": true
+ }
+ ]
+ },
+ {
+ "domain": "Database",
+ "hidden": true,
+ "types": [
+ {
+ "id": "DatabaseId",
+ "type": "string",
+ "description": "Unique identifier of Database object.",
+ "hidden": true
+ },
+ {
+ "id": "Database",
+ "type": "object",
+ "description": "Database object.",
+ "hidden": true,
+ "properties": [
+ { "name": "id", "$ref": "DatabaseId", "description": "Database ID." },
+ { "name": "domain", "type": "string", "description": "Database domain." },
+ { "name": "name", "type": "string", "description": "Database name." },
+ { "name": "version", "type": "string", "description": "Database version." }
+ ]
+ },
+ {
+ "id": "Error",
+ "type": "object",
+ "description": "Database error.",
+ "properties": [
+ { "name": "message", "type": "string", "description": "Error message." },
+ { "name": "code", "type": "integer", "description": "Error code." }
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables database tracking, database events will now be delivered to the client."
+ },
+ {
+ "name": "disable",
+ "description": "Disables database tracking, prevents database events from being sent to the client."
+ },
+ {
+ "name": "getDatabaseTableNames",
+ "parameters": [
+ { "name": "databaseId", "$ref": "DatabaseId" }
+ ],
+ "returns": [
+ { "name": "tableNames", "type": "array", "items": { "type": "string" } }
+ ]
+ },
+ {
+ "name": "executeSQL",
+ "async": true,
+ "parameters": [
+ { "name": "databaseId", "$ref": "DatabaseId" },
+ { "name": "query", "type": "string" }
+ ],
+ "returns": [
+ { "name": "columnNames", "type": "array", "optional": true, "items": { "type": "string" } },
+ { "name": "values", "type": "array", "optional": true, "items": { "type": "any" }},
+ { "name": "sqlError", "$ref": "Error", "optional": true }
+ ]
+ }
+ ],
+ "events": [
+ {
+ "name": "addDatabase",
+ "parameters": [
+ { "name": "database", "$ref": "Database" }
+ ]
+ }
+ ]
+ },
+ {
+ "domain": "IndexedDB",
+ "hidden": true,
+ "types": [
+ {
+ "id": "DatabaseWithObjectStores",
+ "type": "object",
+ "description": "Database with an array of object stores.",
+ "properties": [
+ { "name": "name", "type": "string", "description": "Database name." },
+ { "name": "version", "type": "integer", "description": "Database version." },
+ { "name": "objectStores", "type": "array", "items": { "$ref": "ObjectStore" }, "description": "Object stores in this database." }
+ ]
+ },
+ {
+ "id": "ObjectStore",
+ "type": "object",
+ "description": "Object store.",
+ "properties": [
+ { "name": "name", "type": "string", "description": "Object store name." },
+ { "name": "keyPath", "$ref": "KeyPath", "description": "Object store key path." },
+ { "name": "autoIncrement", "type": "boolean", "description": "If true, object store has auto increment flag set." },
+ { "name": "indexes", "type": "array", "items": { "$ref": "ObjectStoreIndex" }, "description": "Indexes in this object store." }
+ ]
+ },
+ {
+ "id": "ObjectStoreIndex",
+ "type": "object",
+ "description": "Object store index.",
+ "properties": [
+ { "name": "name", "type": "string", "description": "Index name." },
+ { "name": "keyPath", "$ref": "KeyPath", "description": "Index key path." },
+ { "name": "unique", "type": "boolean", "description": "If true, index is unique." },
+ { "name": "multiEntry", "type": "boolean", "description": "If true, index allows multiple entries for a key." }
+ ]
+ },
+ {
+ "id": "Key",
+ "type": "object",
+ "description": "Key.",
+ "properties": [
+ { "name": "type", "type": "string", "enum": ["number", "string", "date", "array"], "description": "Key type." },
+ { "name": "number", "type": "number", "optional": true, "description": "Number value." },
+ { "name": "string", "type": "string", "optional": true, "description": "String value." },
+ { "name": "date", "type": "number", "optional": true, "description": "Date value." },
+ { "name": "array", "type": "array", "optional": true, "items": { "$ref": "Key" }, "description": "Array value." }
+ ]
+ },
+ {
+ "id": "KeyRange",
+ "type": "object",
+ "description": "Key range.",
+ "properties": [
+ { "name": "lower", "$ref": "Key", "optional": true, "description": "Lower bound." },
+ { "name": "upper", "$ref": "Key", "optional": true, "description": "Upper bound." },
+ { "name": "lowerOpen", "type": "boolean", "description": "If true lower bound is open." },
+ { "name": "upperOpen", "type": "boolean", "description": "If true upper bound is open." }
+ ]
+ },
+ {
+ "id": "DataEntry",
+ "type": "object",
+ "description": "Data entry.",
+ "properties": [
+ { "name": "key", "$ref": "Runtime.RemoteObject", "description": "Key." },
+ { "name": "primaryKey", "$ref": "Runtime.RemoteObject", "description": "Primary key." },
+ { "name": "value", "$ref": "Runtime.RemoteObject", "description": "Value." }
+ ]
+ },
+ {
+ "id": "KeyPath",
+ "type": "object",
+ "description": "Key path.",
+ "properties": [
+ { "name": "type", "type": "string", "enum": ["null", "string", "array"], "description": "Key path type." },
+ { "name": "string", "type": "string", "optional": true, "description": "String value." },
+ { "name": "array", "type": "array", "optional": true, "items": { "type": "string" }, "description": "Array value." }
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables events from backend."
+ },
+ {
+ "name": "disable",
+ "description": "Disables events from backend."
+ },
+ {
+ "name": "requestDatabaseNames",
+ "async": true,
+ "parameters": [
+ { "name": "securityOrigin", "type": "string", "description": "Security origin." }
+ ],
+ "returns": [
+ { "name": "databaseNames", "type": "array", "items": { "type": "string" }, "description": "Database names for origin." }
+ ],
+ "description": "Requests database names for given security origin."
+ },
+ {
+ "name": "requestDatabase",
+ "async": true,
+ "parameters": [
+ { "name": "securityOrigin", "type": "string", "description": "Security origin." },
+ { "name": "databaseName", "type": "string", "description": "Database name." }
+ ],
+ "returns": [
+ { "name": "databaseWithObjectStores", "$ref": "DatabaseWithObjectStores", "description": "Database with an array of object stores." }
+ ],
+ "description": "Requests database with given name in given frame."
+ },
+ {
+ "name": "requestData",
+ "async": true,
+ "parameters": [
+ { "name": "securityOrigin", "type": "string", "description": "Security origin." },
+ { "name": "databaseName", "type": "string", "description": "Database name." },
+ { "name": "objectStoreName", "type": "string", "description": "Object store name." },
+ { "name": "indexName", "type": "string", "description": "Index name, empty string for object store data requests." },
+ { "name": "skipCount", "type": "integer", "description": "Number of records to skip." },
+ { "name": "pageSize", "type": "integer", "description": "Number of records to fetch." },
+ { "name": "keyRange", "$ref": "KeyRange", "optional": true, "description": "Key range." }
+ ],
+ "returns": [
+ { "name": "objectStoreDataEntries", "type": "array", "items": { "$ref": "DataEntry" }, "description": "Array of object store data entries." },
+ { "name": "hasMore", "type": "boolean", "description": "If true, there are more entries to fetch in the given range." }
+ ],
+ "description": "Requests data from object store or index."
+ },
+ {
+ "name": "clearObjectStore",
+ "async": true,
+ "parameters": [
+ { "name": "securityOrigin", "type": "string", "description": "Security origin." },
+ { "name": "databaseName", "type": "string", "description": "Database name." },
+ { "name": "objectStoreName", "type": "string", "description": "Object store name." }
+ ],
+ "returns": [
+ ],
+ "description": "Clears all entries from an object store."
+ }
+ ]
+ },
+ {
+ "domain": "DOMStorage",
+ "hidden": true,
+ "description": "Query and modify DOM storage.",
+ "types": [
+ {
+ "id": "StorageId",
+ "type": "object",
+ "description": "DOM Storage identifier.",
+ "hidden": true,
+ "properties": [
+ { "name": "securityOrigin", "type": "string", "description": "Security origin for the storage." },
+ { "name": "isLocalStorage", "type": "boolean", "description": "Whether the storage is local storage (not session storage)." }
+ ]
+ },
+ {
+ "id": "Item",
+ "type": "array",
+ "description": "DOM Storage item.",
+ "hidden": true,
+ "items": { "type": "string" }
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables storage tracking, storage events will now be delivered to the client."
+ },
+ {
+ "name": "disable",
+ "description": "Disables storage tracking, prevents storage events from being sent to the client."
+ },
+ {
+ "name": "getDOMStorageItems",
+ "parameters": [
+ { "name": "storageId", "$ref": "StorageId" }
+ ],
+ "returns": [
+ { "name": "entries", "type": "array", "items": { "$ref": "Item" } }
+ ]
+ },
+ {
+ "name": "setDOMStorageItem",
+ "parameters": [
+ { "name": "storageId", "$ref": "StorageId" },
+ { "name": "key", "type": "string" },
+ { "name": "value", "type": "string" }
+ ]
+ },
+ {
+ "name": "removeDOMStorageItem",
+ "parameters": [
+ { "name": "storageId", "$ref": "StorageId" },
+ { "name": "key", "type": "string" }
+ ]
+ }
+ ],
+ "events": [
+ {
+ "name": "domStorageItemsCleared",
+ "parameters": [
+ { "name": "storageId", "$ref": "StorageId" }
+ ]
+ },
+ {
+ "name": "domStorageItemRemoved",
+ "parameters": [
+ { "name": "storageId", "$ref": "StorageId" },
+ { "name": "key", "type": "string" }
+ ]
+ },
+ {
+ "name": "domStorageItemAdded",
+ "parameters": [
+ { "name": "storageId", "$ref": "StorageId" },
+ { "name": "key", "type": "string" },
+ { "name": "newValue", "type": "string" }
+ ]
+ },
+ {
+ "name": "domStorageItemUpdated",
+ "parameters": [
+ { "name": "storageId", "$ref": "StorageId" },
+ { "name": "key", "type": "string" },
+ { "name": "oldValue", "type": "string" },
+ { "name": "newValue", "type": "string" }
+ ]
+ }
+ ]
+ },
+ {
+ "domain": "ApplicationCache",
+ "hidden": true,
+ "types": [
+ {
+ "id": "ApplicationCacheResource",
+ "type": "object",
+ "description": "Detailed application cache resource information.",
+ "properties": [
+ { "name": "url", "type": "string", "description": "Resource url." },
+ { "name": "size", "type": "integer", "description": "Resource size." },
+ { "name": "type", "type": "string", "description": "Resource type." }
+ ]
+ },
+ {
+ "id": "ApplicationCache",
+ "type": "object",
+ "description": "Detailed application cache information.",
+ "properties": [
+ { "name": "manifestURL", "type": "string", "description": "Manifest URL." },
+ { "name": "size", "type": "number", "description": "Application cache size." },
+ { "name": "creationTime", "type": "number", "description": "Application cache creation time." },
+ { "name": "updateTime", "type": "number", "description": "Application cache update time." },
+ { "name": "resources", "type": "array", "items": { "$ref": "ApplicationCacheResource" }, "description": "Application cache resources." }
+ ]
+ },
+ {
+ "id": "FrameWithManifest",
+ "type": "object",
+ "description": "Frame identifier - manifest URL pair.",
+ "properties": [
+ { "name": "frameId", "$ref": "Page.FrameId", "description": "Frame identifier." },
+ { "name": "manifestURL", "type": "string", "description": "Manifest URL." },
+ { "name": "status", "type": "integer", "description": "Application cache status." }
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "getFramesWithManifests",
+ "returns": [
+ { "name": "frameIds", "type": "array", "items": { "$ref": "FrameWithManifest" }, "description": "Array of frame identifiers with manifest urls for each frame containing a document associated with some application cache." }
+ ],
+ "description": "Returns array of frame identifiers with manifest urls for each frame containing a document associated with some application cache."
+ },
+ {
+ "name": "enable",
+ "description": "Enables application cache domain notifications."
+ },
+ {
+ "name": "getManifestForFrame",
+ "parameters": [
+ { "name": "frameId", "$ref": "Page.FrameId", "description": "Identifier of the frame containing document whose manifest is retrieved." }
+ ],
+ "returns": [
+ { "name": "manifestURL", "type": "string", "description": "Manifest URL for document in the given frame." }
+ ],
+ "description": "Returns manifest URL for document in the given frame."
+ },
+ {
+ "name": "getApplicationCacheForFrame",
+ "parameters": [
+ { "name": "frameId", "$ref": "Page.FrameId", "description": "Identifier of the frame containing document whose application cache is retrieved." }
+ ],
+ "returns": [
+ { "name": "applicationCache", "$ref": "ApplicationCache", "description": "Relevant application cache data for the document in given frame." }
+ ],
+ "description": "Returns relevant application cache data for the document in given frame."
+ }
+ ],
+ "events": [
+ {
+ "name": "applicationCacheStatusUpdated",
+ "parameters": [
+ { "name": "frameId", "$ref": "Page.FrameId", "description": "Identifier of the frame containing document whose application cache updated status." },
+ { "name": "manifestURL", "type": "string", "description": "Manifest URL." },
+ { "name": "status", "type": "integer", "description": "Updated application cache status." }
+ ]
+ },
+ {
+ "name": "networkStateUpdated",
+ "parameters": [
+ { "name": "isNowOnline", "type": "boolean" }
+ ]
+ }
+ ]
+ },
+ {
+ "domain": "FileSystem",
+ "hidden": true,
+ "types": [
+ {
+ "id": "Entry",
+ "type": "object",
+ "properties": [
+ { "name": "url", "type": "string", "description": "filesystem: URL for the entry." },
+ { "name": "name", "type": "string", "description": "The name of the file or directory." },
+ { "name": "isDirectory", "type": "boolean", "description": "True if the entry is a directory." },
+ { "name": "mimeType", "type": "string", "optional": true, "description": "MIME type of the entry, available for a file only." },
+ { "name": "resourceType", "$ref": "Page.ResourceType", "optional": true, "description": "ResourceType of the entry, available for a file only." },
+ { "name": "isTextFile", "type": "boolean", "optional": true, "description": "True if the entry is a text file." }
+ ],
+ "description": "Represents a browser side file or directory."
+ },
+ {
+ "id": "Metadata",
+ "type": "object",
+ "properties": [
+ { "name": "modificationTime", "type": "number", "description": "Modification time." },
+ { "name": "size", "type": "number", "description": "File size. This field is always zero for directories." }
+ ],
+ "description": "Represents metadata of a file or entry."
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables events from backend."
+ },
+ {
+ "name": "disable",
+ "description": "Disables events from backend."
+ },
+ {
+ "name": "requestFileSystemRoot",
+ "async": true,
+ "parameters": [
+ { "name": "origin", "type": "string", "description": "Security origin of requesting FileSystem. One of frames in current page needs to have this security origin." },
+ { "name": "type", "type": "string", "enum": ["temporary", "persistent"], "description": "FileSystem type of requesting FileSystem." }
+ ],
+ "returns": [
+ { "name": "errorCode", "type": "integer", "description": "0, if no error. Otherwise, errorCode is set to FileError::ErrorCode value." },
+ { "name": "root", "$ref": "Entry", "optional": true, "description": "Contains root of the requested FileSystem if the command completed successfully." }
+ ],
+ "description": "Returns root directory of the FileSystem, if exists."
+ },
+ {
+ "name": "requestDirectoryContent",
+ "async": true,
+ "parameters": [
+ { "name": "url", "type": "string", "description": "URL of the directory that the frontend is requesting to read from." }
+ ],
+ "returns": [
+ { "name": "errorCode", "type": "integer", "description": "0, if no error. Otherwise, errorCode is set to FileError::ErrorCode value." },
+ { "name": "entries", "type": "array", "items": { "$ref": "Entry" }, "optional": true, "description": "Contains all entries on directory if the command completed successfully." }
+ ],
+ "description": "Returns content of the directory."
+ },
+ {
+ "name": "requestMetadata",
+ "async": true,
+ "parameters": [
+ { "name": "url", "type": "string", "description": "URL of the entry that the frontend is requesting to get metadata from." }
+ ],
+ "returns": [
+ { "name": "errorCode", "type": "integer", "description": "0, if no error. Otherwise, errorCode is set to FileError::ErrorCode value." },
+ { "name": "metadata", "$ref": "Metadata", "optional": true, "description": "Contains metadata of the entry if the command completed successfully." }
+ ],
+ "description": "Returns metadata of the entry."
+ },
+ {
+ "name": "requestFileContent",
+ "async": true,
+ "parameters": [
+ { "name": "url", "type": "string", "description": "URL of the file that the frontend is requesting to read from." },
+ { "name": "readAsText", "type": "boolean", "description": "True if the content should be read as text, otherwise the result will be returned as base64 encoded text." },
+ { "name": "start", "type": "integer", "optional": true, "description": "Specifies the start of range to read." },
+ { "name": "end", "type": "integer", "optional": true, "description": "Specifies the end of range to read exclusively." },
+ { "name": "charset", "type": "string", "optional": true, "description": "Overrides charset of the content when content is served as text." }
+ ],
+ "returns": [
+ { "name": "errorCode", "type": "integer", "description": "0, if no error. Otherwise, errorCode is set to FileError::ErrorCode value." },
+ { "name": "content", "type": "string", "optional": true, "description": "Content of the file." },
+ { "name": "charset", "type": "string", "optional": true, "description": "Charset of the content if it is served as text." }
+ ],
+ "description": "Returns content of the file. Result should be sliced into [start, end)."
+ },
+ {
+ "name": "deleteEntry",
+ "async": true,
+ "parameters": [
+ { "name": "url", "type": "string", "description": "URL of the entry to delete." }
+ ],
+ "returns": [
+ { "name": "errorCode", "type": "integer", "description": "0, if no error. Otherwise errorCode is set to FileError::ErrorCode value." }
+ ],
+ "description": "Deletes specified entry. If the entry is a directory, the agent deletes children recursively."
+ }
+ ]
+ },
+ {
+ "domain": "DOM",
+ "description": "This domain exposes DOM read/write operations. Each DOM Node is represented with its mirror object that has an <code>id</code>. This <code>id</code> can be used to get additional information on the Node, resolve it into the JavaScript object wrapper, etc. It is important that client receives DOM events only for the nodes that are known to the client. Backend keeps track of the nodes that were sent to the client and never sends the same node twice. It is client's responsibility to collect information about the nodes that were sent to the client.<p>Note that <code>iframe</code> owner elements will return corresponding document elements as their child nodes.</p>",
+ "types": [
+ {
+ "id": "NodeId",
+ "type": "integer",
+ "description": "Unique DOM node identifier."
+ },
+ {
+ "id": "BackendNodeId",
+ "type": "integer",
+ "description": "Unique DOM node identifier used to reference a node that may not have been pushed to the front-end.",
+ "hidden": true
+ },
+ {
+ "id": "Node",
+ "type": "object",
+ "properties": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Node identifier that is passed into the rest of the DOM messages as the <code>nodeId</code>. Backend will only push node with given <code>id</code> once. It is aware of all requested nodes and will only fire DOM events for nodes known to the client." },
+ { "name": "nodeType", "type": "integer", "description": "<code>Node</code>'s nodeType." },
+ { "name": "nodeName", "type": "string", "description": "<code>Node</code>'s nodeName." },
+ { "name": "localName", "type": "string", "description": "<code>Node</code>'s localName." },
+ { "name": "nodeValue", "type": "string", "description": "<code>Node</code>'s nodeValue." },
+ { "name": "childNodeCount", "type": "integer", "optional": true, "description": "Child count for <code>Container</code> nodes." },
+ { "name": "children", "type": "array", "optional": true, "items": { "$ref": "Node" }, "description": "Child nodes of this node when requested with children." },
+ { "name": "attributes", "type": "array", "optional": true, "items": { "type": "string" }, "description": "Attributes of the <code>Element</code> node in the form of flat array <code>[name1, value1, name2, value2]</code>." },
+ { "name": "documentURL", "type": "string", "optional": true, "description": "Document URL that <code>Document</code> or <code>FrameOwner</code> node points to." },
+ { "name": "baseURL", "type": "string", "optional": true, "description": "Base URL that <code>Document</code> or <code>FrameOwner</code> node uses for URL completion.", "hidden": true },
+ { "name": "publicId", "type": "string", "optional": true, "description": "<code>DocumentType</code>'s publicId." },
+ { "name": "systemId", "type": "string", "optional": true, "description": "<code>DocumentType</code>'s systemId." },
+ { "name": "internalSubset", "type": "string", "optional": true, "description": "<code>DocumentType</code>'s internalSubset." },
+ { "name": "xmlVersion", "type": "string", "optional": true, "description": "<code>Document</code>'s XML version in case of XML documents." },
+ { "name": "name", "type": "string", "optional": true, "description": "<code>Attr</code>'s name." },
+ { "name": "value", "type": "string", "optional": true, "description": "<code>Attr</code>'s value." },
+ { "name": "frameId", "$ref": "Page.FrameId", "optional": true, "description": "Frame ID for frame owner elements.", "hidden": true },
+ { "name": "contentDocument", "$ref": "Node", "optional": true, "description": "Content document for frame owner elements." },
+ { "name": "shadowRoots", "type": "array", "optional": true, "items": { "$ref": "Node" }, "description": "Shadow root list for given element host.", "hidden": true },
+ { "name": "templateContent", "$ref": "Node", "optional": true, "description": "Content document fragment for template elements", "hidden": true }
+ ],
+ "description": "DOM interaction is implemented in terms of mirror objects that represent the actual DOM nodes. DOMNode is a base node mirror type."
+ },
+ {
+ "id": "EventListener",
+ "type": "object",
+ "hidden": true,
+ "properties": [
+ { "name": "type", "type": "string", "description": "<code>EventListener</code>'s type." },
+ { "name": "useCapture", "type": "boolean", "description": "<code>EventListener</code>'s useCapture." },
+ { "name": "isAttribute", "type": "boolean", "description": "<code>EventListener</code>'s isAttribute." },
+ { "name": "nodeId", "$ref": "NodeId", "description": "Target <code>DOMNode</code> id." },
+ { "name": "handlerBody", "type": "string", "description": "Event handler function body." },
+ { "name": "location", "$ref": "Debugger.Location", "optional": true, "description": "Handler code location." },
+ { "name": "sourceName", "type": "string", "optional": true, "description": "Source script URL." },
+ { "name": "handler", "$ref": "Runtime.RemoteObject", "optional": true, "description": "Event handler function value." }
+ ],
+ "description": "DOM interaction is implemented in terms of mirror objects that represent the actual DOM nodes. DOMNode is a base node mirror type."
+ },
+ {
+ "id": "RGBA",
+ "type": "object",
+ "properties": [
+ { "name": "r", "type": "integer", "description": "The red component, in the [0-255] range." },
+ { "name": "g", "type": "integer", "description": "The green component, in the [0-255] range." },
+ { "name": "b", "type": "integer", "description": "The blue component, in the [0-255] range." },
+ { "name": "a", "type": "number", "optional": true, "description": "The alpha component, in the [0-1] range (default: 1)." }
+ ],
+ "description": "A structure holding an RGBA color."
+ },
+ {
+ "id": "Quad",
+ "type": "array",
+ "items": { "type": "number" },
+ "minItems": 8,
+ "maxItems": 8,
+ "description": "An array of quad vertices, x immediately followed by y for each point, points clock-wise.",
+ "hidden": true
+ },
+ {
+ "id": "BoxModel",
+ "type": "object",
+ "hidden": true,
+ "properties": [
+ { "name": "content", "$ref": "Quad", "description": "Content box" },
+ { "name": "padding", "$ref": "Quad", "description": "Padding box" },
+ { "name": "border", "$ref": "Quad", "description": "Border box" },
+ { "name": "margin", "$ref": "Quad", "description": "Margin box" },
+ { "name": "width", "type": "integer", "description": "Node width" },
+ { "name": "height", "type": "integer", "description": "Node height" },
+ { "name": "shapeOutside", "type": "string", "description": "CSS Shape Outside" }
+ ],
+ "description": "Box model."
+ },
+ {
+ "id": "Rect",
+ "type": "object",
+ "hidden": true,
+ "properties": [
+ { "name": "x", "type": "number", "description": "X coordinate" },
+ { "name": "y", "type": "number", "description": "Y coordinate" },
+ { "name": "width", "type": "number", "description": "Rectangle width" },
+ { "name": "height", "type": "number", "description": "Rectangle height" }
+ ],
+ "description": "Rectangle."
+ },
+ {
+ "id": "HighlightConfig",
+ "type": "object",
+ "properties": [
+ { "name": "showInfo", "type": "boolean", "optional": true, "description": "Whether the node info tooltip should be shown (default: false)." },
+ { "name": "contentColor", "$ref": "RGBA", "optional": true, "description": "The content box highlight fill color (default: transparent)." },
+ { "name": "paddingColor", "$ref": "RGBA", "optional": true, "description": "The padding highlight fill color (default: transparent)." },
+ { "name": "borderColor", "$ref": "RGBA", "optional": true, "description": "The border highlight fill color (default: transparent)." },
+ { "name": "marginColor", "$ref": "RGBA", "optional": true, "description": "The margin highlight fill color (default: transparent)." },
+ { "name": "eventTargetColor", "$ref": "RGBA", "optional": true, "hidden": true, "description": "The event target element highlight fill color (default: transparent)." }
+ ],
+ "description": "Configuration data for the highlighting of page elements."
+ }
+ ],
+ "commands": [
+ {
+ "name": "getDocument",
+ "returns": [
+ { "name": "root", "$ref": "Node", "description": "Resulting node." }
+ ],
+ "description": "Returns the root DOM node to the caller."
+ },
+ {
+ "name": "requestChildNodes",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to get children for." },
+ { "name": "depth", "type": "integer", "optional": true, "description": "The maximum depth at which children should be retrieved, defaults to 1. Use -1 for the entire subtree or provide an integer larger than 0.", "hidden": true }
+ ],
+ "description": "Requests that children of the node with given id are returned to the caller in form of <code>setChildNodes</code> events where not only immediate children are retrieved, but all children down to the specified depth."
+ },
+ {
+ "name": "querySelector",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to query upon." },
+ { "name": "selector", "type": "string", "description": "Selector string." }
+ ],
+ "returns": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Query selector result." }
+ ],
+ "description": "Executes <code>querySelector</code> on a given node."
+ },
+ {
+ "name": "querySelectorAll",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to query upon." },
+ { "name": "selector", "type": "string", "description": "Selector string." }
+ ],
+ "returns": [
+ { "name": "nodeIds", "type": "array", "items": { "$ref": "NodeId" }, "description": "Query selector result." }
+ ],
+ "description": "Executes <code>querySelectorAll</code> on a given node."
+ },
+ {
+ "name": "setNodeName",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to set name for." },
+ { "name": "name", "type": "string", "description": "New node's name." }
+ ],
+ "returns": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "New node's id." }
+ ],
+ "description": "Sets node name for a node with given id."
+ },
+ {
+ "name": "setNodeValue",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to set value for." },
+ { "name": "value", "type": "string", "description": "New node's value." }
+ ],
+ "description": "Sets node value for a node with given id."
+ },
+ {
+ "name": "removeNode",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to remove." }
+ ],
+ "description": "Removes node with given id."
+ },
+ {
+ "name": "setAttributeValue",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the element to set attribute for." },
+ { "name": "name", "type": "string", "description": "Attribute name." },
+ { "name": "value", "type": "string", "description": "Attribute value." }
+ ],
+ "description": "Sets attribute for an element with given id."
+ },
+ {
+ "name": "setAttributesAsText",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the element to set attributes for." },
+ { "name": "text", "type": "string", "description": "Text with a number of attributes. Will parse this text using HTML parser." },
+ { "name": "name", "type": "string", "optional": true, "description": "Attribute name to replace with new attributes derived from text in case text parsed successfully." }
+ ],
+ "description": "Sets attributes on element with given id. This method is useful when user edits some existing attribute value and types in several attribute name/value pairs."
+ },
+ {
+ "name": "removeAttribute",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the element to remove attribute from." },
+ { "name": "name", "type": "string", "description": "Name of the attribute to remove." }
+ ],
+ "description": "Removes attribute with given name from an element with given id."
+ },
+ {
+ "name": "getEventListenersForNode",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to get listeners for." },
+ { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name for handler value. Handler value is not returned without this parameter specified." }
+ ],
+ "returns": [
+ { "name": "listeners", "type": "array", "items": { "$ref": "EventListener"}, "description": "Array of relevant listeners." }
+ ],
+ "description": "Returns event listeners relevant to the node.",
+ "hidden": true
+ },
+ {
+ "name": "getOuterHTML",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to get markup for." }
+ ],
+ "returns": [
+ { "name": "outerHTML", "type": "string", "description": "Outer HTML markup." }
+ ],
+ "description": "Returns node's HTML markup."
+ },
+ {
+ "name": "setOuterHTML",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to set markup for." },
+ { "name": "outerHTML", "type": "string", "description": "Outer HTML markup to set." }
+ ],
+ "description": "Sets node HTML markup, returns new node id."
+ },
+ {
+ "name": "performSearch",
+ "parameters": [
+ { "name": "query", "type": "string", "description": "Plain text or query selector or XPath search query." }
+ ],
+ "returns": [
+ { "name": "searchId", "type": "string", "description": "Unique search session identifier." },
+ { "name": "resultCount", "type": "integer", "description": "Number of search results." }
+ ],
+ "description": "Searches for a given string in the DOM tree. Use <code>getSearchResults</code> to access search results or <code>cancelSearch</code> to end this search session.",
+ "hidden": true
+ },
+ {
+ "name": "getSearchResults",
+ "parameters": [
+ { "name": "searchId", "type": "string", "description": "Unique search session identifier." },
+ { "name": "fromIndex", "type": "integer", "description": "Start index of the search result to be returned." },
+ { "name": "toIndex", "type": "integer", "description": "End index of the search result to be returned." }
+ ],
+ "returns": [
+ { "name": "nodeIds", "type": "array", "items": { "$ref": "NodeId" }, "description": "Ids of the search result nodes." }
+ ],
+ "description": "Returns search results from given <code>fromIndex</code> to given <code>toIndex</code> from the sarch with the given identifier.",
+ "hidden": true
+ },
+ {
+ "name": "discardSearchResults",
+ "parameters": [
+ { "name": "searchId", "type": "string", "description": "Unique search session identifier." }
+ ],
+ "description": "Discards search results from the session with the given id. <code>getSearchResults</code> should no longer be called for that search.",
+ "hidden": true
+ },
+ {
+ "name": "requestNode",
+ "parameters": [
+ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "JavaScript object id to convert into node." }
+ ],
+ "returns": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Node id for given object." }
+ ],
+ "description": "Requests that the node is sent to the caller given the JavaScript node object reference. All nodes that form the path from the node to the root are also sent to the client as a series of <code>setChildNodes</code> notifications."
+ },
+ {
+ "name": "setInspectModeEnabled",
+ "hidden": true,
+ "parameters": [
+ { "name": "enabled", "type": "boolean", "description": "True to enable inspection mode, false to disable it." },
+ { "name": "inspectShadowDOM", "type": "boolean", "optional": true, "description": "True to enable inspection mode for shadow DOM." },
+ { "name": "highlightConfig", "$ref": "HighlightConfig", "optional": true, "description": "A descriptor for the highlight appearance of hovered-over nodes. May be omitted if <code>enabled == false</code>." }
+ ],
+ "description": "Enters the 'inspect' mode. In this mode, elements that user is hovering over are highlighted. Backend then generates 'inspectNodeRequested' event upon element selection."
+ },
+ {
+ "name": "highlightRect",
+ "parameters": [
+ { "name": "x", "type": "integer", "description": "X coordinate" },
+ { "name": "y", "type": "integer", "description": "Y coordinate" },
+ { "name": "width", "type": "integer", "description": "Rectangle width" },
+ { "name": "height", "type": "integer", "description": "Rectangle height" },
+ { "name": "color", "$ref": "RGBA", "optional": true, "description": "The highlight fill color (default: transparent)." },
+ { "name": "outlineColor", "$ref": "RGBA", "optional": true, "description": "The highlight outline color (default: transparent)." }
+ ],
+ "description": "Highlights given rectangle. Coordinates are absolute with respect to the main frame viewport."
+ },
+ {
+ "name": "highlightQuad",
+ "parameters": [
+ { "name": "quad", "$ref": "Quad", "description": "Quad to highlight" },
+ { "name": "color", "$ref": "RGBA", "optional": true, "description": "The highlight fill color (default: transparent)." },
+ { "name": "outlineColor", "$ref": "RGBA", "optional": true, "description": "The highlight outline color (default: transparent)." }
+ ],
+ "description": "Highlights given quad. Coordinates are absolute with respect to the main frame viewport.",
+ "hidden": true
+ },
+ {
+ "name": "highlightNode",
+ "parameters": [
+ { "name": "highlightConfig", "$ref": "HighlightConfig", "description": "A descriptor for the highlight appearance." },
+ { "name": "nodeId", "$ref": "NodeId", "optional": true, "description": "Identifier of the node to highlight." },
+ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "optional": true, "description": "JavaScript object id of the node to be highlighted.", "hidden": true }
+ ],
+ "description": "Highlights DOM node with given id or with the given JavaScript object wrapper. Either nodeId or objectId must be specified."
+ },
+ {
+ "name": "hideHighlight",
+ "description": "Hides DOM node highlight."
+ },
+ {
+ "name": "highlightFrame",
+ "parameters": [
+ { "name": "frameId", "$ref": "Page.FrameId", "description": "Identifier of the frame to highlight." },
+ { "name": "contentColor", "$ref": "RGBA", "optional": true, "description": "The content box highlight fill color (default: transparent)." },
+ { "name": "contentOutlineColor", "$ref": "RGBA", "optional": true, "description": "The content box highlight outline color (default: transparent)." }
+ ],
+ "description": "Highlights owner element of the frame with given id.",
+ "hidden": true
+ },
+ {
+ "name": "pushNodeByPathToFrontend",
+ "parameters": [
+ { "name": "path", "type": "string", "description": "Path to node in the proprietary format." }
+ ],
+ "returns": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node for given path." }
+ ],
+ "description": "Requests that the node is sent to the caller given its path. // FIXME, use XPath",
+ "hidden": true
+ },
+ {
+ "name": "pushNodeByBackendIdToFrontend",
+ "parameters": [
+ { "name": "backendNodeId", "$ref": "BackendNodeId", "description": "The backend node id of the node." }
+ ],
+ "returns": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "The pushed node's id." }
+ ],
+ "description": "Requests that the node is sent to the caller given its backend node id.",
+ "hidden": true
+ },
+ {
+ "name": "releaseBackendNodeIds",
+ "parameters": [
+ { "name": "nodeGroup", "type": "string", "description": "The backend node ids group name." }
+ ],
+ "description": "Requests that group of <code>BackendNodeIds</code> is released.",
+ "hidden": true
+ },
+ {
+ "name": "resolveNode",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to resolve." },
+ { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." }
+ ],
+ "returns": [
+ { "name": "object", "$ref": "Runtime.RemoteObject", "description": "JavaScript object wrapper for given node." }
+ ],
+ "description": "Resolves JavaScript node object for given node id."
+ },
+ {
+ "name": "getAttributes",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to retrieve attibutes for." }
+ ],
+ "returns": [
+ { "name": "attributes", "type": "array", "items": { "type": "string" }, "description": "An interleaved array of node attribute names and values." }
+ ],
+ "description": "Returns attributes for the specified node."
+ },
+ {
+ "name": "moveTo",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to drop." },
+ { "name": "targetNodeId", "$ref": "NodeId", "description": "Id of the element to drop into." },
+ { "name": "insertBeforeNodeId", "$ref": "NodeId", "optional": true, "description": "Drop node before given one." }
+ ],
+ "returns": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "New id of the moved node." }
+ ],
+ "description": "Moves node into the new container, places it before the given anchor."
+ },
+ {
+ "name": "undo",
+ "description": "Undoes the last performed action.",
+ "hidden": true
+ },
+ {
+ "name": "redo",
+ "description": "Re-does the last undone action.",
+ "hidden": true
+ },
+ {
+ "name": "markUndoableState",
+ "description": "Marks last undoable state.",
+ "hidden": true
+ },
+ {
+ "name": "focus",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to focus." }
+ ],
+ "description": "Focuses the given element.",
+ "hidden": true
+ },
+ {
+ "name": "setFileInputFiles",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the file input node to set files for." },
+ { "name": "files", "type": "array", "items": { "type": "string" }, "description": "Array of file paths to set." }
+ ],
+ "description": "Sets files for the given file input element.",
+ "hidden": true
+ },
+ {
+ "name": "getBoxModel",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to get box model for." }
+ ],
+ "returns": [
+ { "name": "model", "$ref": "BoxModel", "description": "Box model for the node." }
+ ],
+ "description": "Returns boxes for the currently selected nodes.",
+ "hidden": true
+ },
+ {
+ "name": "getNodeForLocation",
+ "parameters": [
+ { "name": "x", "type": "integer", "description": "X coordinate." },
+ { "name": "y", "type": "integer", "description": "Y coordinate." }
+ ],
+ "returns": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node at given coordinates." }
+ ],
+ "description": "Returns node id at given location.",
+ "hidden": true
+ }
+ ],
+ "events": [
+ {
+ "name": "documentUpdated",
+ "description": "Fired when <code>Document</code> has been totally updated. Node ids are no longer valid."
+ },
+ {
+ "name": "inspectNodeRequested",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to inspect." }
+ ],
+ "description": "Fired when the node should be inspected. This happens after call to <code>setInspectModeEnabled</code>.",
+ "hidden" : true
+ },
+ {
+ "name": "setChildNodes",
+ "parameters": [
+ { "name": "parentId", "$ref": "NodeId", "description": "Parent node id to populate with children." },
+ { "name": "nodes", "type": "array", "items": { "$ref": "Node"}, "description": "Child nodes array." }
+ ],
+ "description": "Fired when backend wants to provide client with the missing DOM structure. This happens upon most of the calls requesting node ids."
+ },
+ {
+ "name": "attributeModified",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node that has changed." },
+ { "name": "name", "type": "string", "description": "Attribute name." },
+ { "name": "value", "type": "string", "description": "Attribute value." }
+ ],
+ "description": "Fired when <code>Element</code>'s attribute is modified."
+ },
+ {
+ "name": "attributeRemoved",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node that has changed." },
+ { "name": "name", "type": "string", "description": "A ttribute name." }
+ ],
+ "description": "Fired when <code>Element</code>'s attribute is removed."
+ },
+ {
+ "name": "inlineStyleInvalidated",
+ "parameters": [
+ { "name": "nodeIds", "type": "array", "items": { "$ref": "NodeId" }, "description": "Ids of the nodes for which the inline styles have been invalidated." }
+ ],
+ "description": "Fired when <code>Element</code>'s inline style is modified via a CSS property modification.",
+ "hidden": true
+ },
+ {
+ "name": "characterDataModified",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node that has changed." },
+ { "name": "characterData", "type": "string", "description": "New text value." }
+ ],
+ "description": "Mirrors <code>DOMCharacterDataModified</code> event."
+ },
+ {
+ "name": "childNodeCountUpdated",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node that has changed." },
+ { "name": "childNodeCount", "type": "integer", "description": "New node count." }
+ ],
+ "description": "Fired when <code>Container</code>'s child node count has changed."
+ },
+ {
+ "name": "childNodeInserted",
+ "parameters": [
+ { "name": "parentNodeId", "$ref": "NodeId", "description": "Id of the node that has changed." },
+ { "name": "previousNodeId", "$ref": "NodeId", "description": "If of the previous siblint." },
+ { "name": "node", "$ref": "Node", "description": "Inserted node data." }
+ ],
+ "description": "Mirrors <code>DOMNodeInserted</code> event."
+ },
+ {
+ "name": "childNodeRemoved",
+ "parameters": [
+ { "name": "parentNodeId", "$ref": "NodeId", "description": "Parent id." },
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node that has been removed." }
+ ],
+ "description": "Mirrors <code>DOMNodeRemoved</code> event."
+ },
+ {
+ "name": "shadowRootPushed",
+ "parameters": [
+ { "name": "hostId", "$ref": "NodeId", "description": "Host element id." },
+ { "name": "root", "$ref": "Node", "description": "Shadow root." }
+ ],
+ "description": "Called when shadow root is pushed into the element.",
+ "hidden": true
+ },
+ {
+ "name": "shadowRootPopped",
+ "parameters": [
+ { "name": "hostId", "$ref": "NodeId", "description": "Host element id." },
+ { "name": "rootId", "$ref": "NodeId", "description": "Shadow root id." }
+ ],
+ "description": "Called when shadow root is popped from the element.",
+ "hidden": true
+ }
+ ]
+ },
+ {
+ "domain": "CSS",
+ "hidden": true,
+ "description": "This domain exposes CSS read/write operations. All CSS objects (stylesheets, rules, and styles) have an associated <code>id</code> used in subsequent operations on the related object. Each object type has a specific <code>id</code> structure, and those are not interchangeable between objects of different kinds. CSS objects can be loaded using the <code>get*ForNode()</code> calls (which accept a DOM node id). A client can also discover all the existing stylesheets with the <code>getAllStyleSheets()</code> method (or keeping track of the <code>styleSheetAdded</code>/<code>styleSheetRemoved</code> events) and subsequently load the required stylesheet contents using the <code>getStyleSheet[Text]()</code> methods.",
+ "types": [
+ {
+ "id": "StyleSheetId",
+ "type": "string"
+ },
+ {
+ "id": "CSSStyleId",
+ "type": "object",
+ "properties": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId", "description": "Enclosing stylesheet identifier." },
+ { "name": "ordinal", "type": "integer", "description": "The style ordinal within the stylesheet." }
+ ],
+ "description": "This object identifies a CSS style in a unique way."
+ },
+ {
+ "id": "StyleSheetOrigin",
+ "type": "string",
+ "enum": ["user", "user-agent", "inspector", "regular"],
+ "description": "Stylesheet type: \"user\" for user stylesheets, \"user-agent\" for user-agent stylesheets, \"inspector\" for stylesheets created by the inspector (i.e. those holding the \"via inspector\" rules), \"regular\" for regular stylesheets."
+ },
+ {
+ "id": "CSSRuleId",
+ "type": "object",
+ "properties": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId", "description": "Enclosing stylesheet identifier." },
+ { "name": "ordinal", "type": "integer", "description": "The rule ordinal within the stylesheet." }
+ ],
+ "description": "This object identifies a CSS rule in a unique way."
+ },
+ {
+ "id": "PseudoIdMatches",
+ "type": "object",
+ "properties": [
+ { "name": "pseudoId", "type": "integer", "description": "Pseudo style identifier (see <code>enum PseudoId</code> in <code>ComputedStyleConstants.h</code>)."},
+ { "name": "matches", "type": "array", "items": { "$ref": "RuleMatch" }, "description": "Matches of CSS rules applicable to the pseudo style."}
+ ],
+ "description": "CSS rule collection for a single pseudo style."
+ },
+ {
+ "id": "InheritedStyleEntry",
+ "type": "object",
+ "properties": [
+ { "name": "inlineStyle", "$ref": "CSSStyle", "optional": true, "description": "The ancestor node's inline style, if any, in the style inheritance chain." },
+ { "name": "matchedCSSRules", "type": "array", "items": { "$ref": "RuleMatch" }, "description": "Matches of CSS rules matching the ancestor node in the style inheritance chain." }
+ ],
+ "description": "CSS rule collection for a single pseudo style."
+ },
+ {
+ "id": "RuleMatch",
+ "type": "object",
+ "properties": [
+ { "name": "rule", "$ref": "CSSRule", "description": "CSS rule in the match." },
+ { "name": "matchingSelectors", "type": "array", "items": { "type": "integer" }, "description": "Matching selector indices in the rule's selectorList selectors (0-based)." }
+ ],
+ "description": "Match data for a CSS rule."
+ },
+ {
+ "id": "SelectorList",
+ "type": "object",
+ "properties": [
+ { "name": "selectors", "type": "array", "items": { "type": "string" }, "description": "Selectors in the list." },
+ { "name": "text", "type": "string", "description": "Rule selector text." },
+ { "name": "range", "$ref": "SourceRange", "optional": true, "description": "Rule selector range in the underlying resource (if available)." }
+ ],
+ "description": "Selector list data."
+ },
+ {
+ "id": "CSSStyleAttribute",
+ "type": "object",
+ "properties": [
+ { "name": "name", "type": "string", "description": "DOM attribute name (e.g. \"width\")."},
+ { "name": "style", "$ref": "CSSStyle", "description": "CSS style generated by the respective DOM attribute."}
+ ],
+ "description": "CSS style information for a DOM style attribute."
+ },
+ {
+ "id": "CSSStyleSheetHeader",
+ "type": "object",
+ "properties": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId", "description": "The stylesheet identifier."},
+ { "name": "frameId", "$ref": "Page.FrameId", "description": "Owner frame identifier."},
+ { "name": "sourceURL", "type": "string", "description": "Stylesheet resource URL."},
+ { "name": "sourceMapURL", "type": "string", "optional": true, "description": "URL of source map associated with the stylesheet (if any)." },
+ { "name": "origin", "$ref": "StyleSheetOrigin", "description": "Stylesheet origin."},
+ { "name": "title", "type": "string", "description": "Stylesheet title."},
+ { "name": "disabled", "type": "boolean", "description": "Denotes whether the stylesheet is disabled."},
+ { "name": "hasSourceURL", "type": "boolean", "optional": true, "description": "Whether the sourceURL field value comes from the sourceURL comment." },
+ { "name": "isInline", "type": "boolean", "description": "Whether this stylesheet is created for STYLE tag by parser. This flag is not set for document.written STYLE tags." },
+ { "name": "startLine", "type": "number", "description": "Line offset of the stylesheet within the resource (zero based)." },
+ { "name": "startColumn", "type": "number", "description": "Column offset of the stylesheet within the resource (zero based)." }
+ ],
+ "description": "CSS stylesheet metainformation."
+ },
+ {
+ "id": "CSSStyleSheetBody",
+ "type": "object",
+ "properties": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId", "description": "The stylesheet identifier."},
+ { "name": "rules", "type": "array", "items": { "$ref": "CSSRule" }, "description": "Stylesheet resource URL."},
+ { "name": "text", "type": "string", "optional": true, "description": "Stylesheet resource contents (if available)."}
+ ],
+ "description": "CSS stylesheet contents."
+ },
+ {
+ "id": "CSSRule",
+ "type": "object",
+ "properties": [
+ { "name": "ruleId", "$ref": "CSSRuleId", "optional": true, "description": "The CSS rule identifier (absent for user agent stylesheet and user-specified stylesheet rules)."},
+ { "name": "selectorList", "$ref": "SelectorList", "description": "Rule selector data." },
+ { "name": "sourceURL", "type": "string", "optional": true, "description": "Parent stylesheet resource URL (for regular rules)."},
+ { "name": "origin", "$ref": "StyleSheetOrigin", "description": "Parent stylesheet's origin."},
+ { "name": "style", "$ref": "CSSStyle", "description": "Associated style declaration." },
+ { "name": "media", "type": "array", "items": { "$ref": "CSSMedia" }, "optional": true, "description": "Media list array (for rules involving media queries). The array enumerates media queries starting with the innermost one, going outwards." }
+ ],
+ "description": "CSS rule representation."
+ },
+ {
+ "id": "SourceRange",
+ "type": "object",
+ "properties": [
+ { "name": "startLine", "type": "integer", "description": "Start line of range." },
+ { "name": "startColumn", "type": "integer", "description": "Start column of range (inclusive)." },
+ { "name": "endLine", "type": "integer", "description": "End line of range" },
+ { "name": "endColumn", "type": "integer", "description": "End column of range (exclusive)." }
+ ],
+ "description": "Text range within a resource. All numbers are zero-based."
+ },
+ {
+ "id": "ShorthandEntry",
+ "type": "object",
+ "properties": [
+ { "name": "name", "type": "string", "description": "Shorthand name." },
+ { "name": "value", "type": "string", "description": "Shorthand value." }
+ ]
+ },
+ {
+ "id": "CSSPropertyInfo",
+ "type": "object",
+ "properties": [
+ { "name": "name", "type": "string", "description": "Property name." },
+ { "name": "longhands", "type": "array", "optional": true, "items": { "type": "string" }, "description": "Longhand property names." }
+ ]
+ },
+ {
+ "id": "CSSComputedStyleProperty",
+ "type": "object",
+ "properties": [
+ { "name": "name", "type": "string", "description": "Computed style property name." },
+ { "name": "value", "type": "string", "description": "Computed style property value." }
+ ]
+ },
+ {
+ "id": "CSSStyle",
+ "type": "object",
+ "properties": [
+ { "name": "styleId", "$ref": "CSSStyleId", "optional": true, "description": "The CSS style identifier (absent for attribute styles)." },
+ { "name": "cssProperties", "type": "array", "items": { "$ref": "CSSProperty" }, "description": "CSS properties in the style." },
+ { "name": "shorthandEntries", "type": "array", "items": { "$ref": "ShorthandEntry" }, "description": "Computed values for all shorthands found in the style." },
+ { "name": "cssText", "type": "string", "optional": true, "description": "Style declaration text (if available)." },
+ { "name": "range", "$ref": "SourceRange", "optional": true, "description": "Style declaration range in the enclosing stylesheet (if available)." },
+ { "name": "width", "type": "string", "optional": true, "description": "The effective \"width\" property value from this style." },
+ { "name": "height", "type": "string", "optional": true, "description": "The effective \"height\" property value from this style." }
+ ],
+ "description": "CSS style representation."
+ },
+ {
+ "id": "CSSProperty",
+ "type": "object",
+ "properties": [
+ { "name": "name", "type": "string", "description": "The property name." },
+ { "name": "value", "type": "string", "description": "The property value." },
+ { "name": "priority", "type": "string", "optional": true, "description": "The property priority (implies \"\" if absent)." },
+ { "name": "implicit", "type": "boolean", "optional": true, "description": "Whether the property is implicit (implies <code>false</code> if absent)." },
+ { "name": "text", "type": "string", "optional": true, "description": "The full property text as specified in the style." },
+ { "name": "parsedOk", "type": "boolean", "optional": true, "description": "Whether the property is understood by the browser (implies <code>true</code> if absent)." },
+ { "name": "status", "type": "string", "enum": ["active", "inactive", "disabled", "style"], "optional": true, "description": "The property status: \"active\" if the property is effective in the style, \"inactive\" if the property is overridden by a same-named property in this style later on, \"disabled\" if the property is disabled by the user, \"style\" (implied if absent) if the property is reported by the browser rather than by the CSS source parser." },
+ { "name": "range", "$ref": "SourceRange", "optional": true, "description": "The entire property range in the enclosing style declaration (if available)." }
+ ],
+ "description": "CSS property declaration data."
+ },
+ {
+ "id": "CSSMedia",
+ "type": "object",
+ "properties": [
+ { "name": "text", "type": "string", "description": "Media query text." },
+ { "name": "source", "type": "string", "enum": ["mediaRule", "importRule", "linkedSheet", "inlineSheet"], "description": "Source of the media query: \"mediaRule\" if specified by a @media rule, \"importRule\" if specified by an @import rule, \"linkedSheet\" if specified by a \"media\" attribute in a linked stylesheet's LINK tag, \"inlineSheet\" if specified by a \"media\" attribute in an inline stylesheet's STYLE tag." },
+ { "name": "sourceURL", "type": "string", "optional": true, "description": "URL of the document containing the media query description." },
+ { "name": "range", "$ref": "SourceRange", "optional": true, "description": "The associated rule (@media or @import) header range in the enclosing stylesheet (if available)." },
+ { "name": "parentStyleSheetId", "$ref": "StyleSheetId", "optional": true, "description": "Identifier of the stylesheet containing this object (if exists)." }
+ ],
+ "description": "CSS media query descriptor."
+ },
+ {
+ "id": "SelectorProfileEntry",
+ "type": "object",
+ "properties": [
+ { "name": "selector", "type": "string", "description": "CSS selector of the corresponding rule." },
+ { "name": "url", "type": "string", "description": "URL of the resource containing the corresponding rule." },
+ { "name": "lineNumber", "type": "integer", "description": "Selector line number in the resource for the corresponding rule." },
+ { "name": "time", "type": "number", "description": "Total time this rule handling contributed to the browser running time during profiling (in milliseconds)." },
+ { "name": "hitCount", "type": "integer", "description": "Number of times this rule was considered a candidate for matching against DOM elements." },
+ { "name": "matchCount", "type": "integer", "description": "Number of times this rule actually matched a DOM element." }
+ ],
+ "description": "CSS selector profile entry."
+ },
+ {
+ "id": "SelectorProfile",
+ "type": "object",
+ "properties": [
+ { "name": "totalTime", "type": "number", "description": "Total processing time for all selectors in the profile (in milliseconds)." },
+ { "name": "data", "type": "array", "items": { "$ref": "SelectorProfileEntry" }, "description": "CSS selector profile entries." }
+ ]
+ },
+ {
+ "id": "Region",
+ "type": "object",
+ "properties": [
+ { "name": "regionOverset", "type": "string", "enum": ["overset", "fit", "empty"], "description": "The \"overset\" attribute of a Named Flow." },
+ { "name": "nodeId", "$ref": "DOM.NodeId", "description": "The corresponding DOM node id." }
+ ],
+ "description": "This object represents a region that flows from a Named Flow.",
+ "hidden": true
+ },
+ {
+ "id": "NamedFlow",
+ "type": "object",
+ "properties": [
+ { "name": "documentNodeId", "$ref": "DOM.NodeId", "description": "The document node id." },
+ { "name": "name", "type": "string", "description": "Named Flow identifier." },
+ { "name": "overset", "type": "boolean", "description": "The \"overset\" attribute of a Named Flow." },
+ { "name": "content", "type": "array", "items": { "$ref": "DOM.NodeId" }, "description": "An array of nodes that flow into the Named Flow." },
+ { "name": "regions", "type": "array", "items": { "$ref": "Region" }, "description": "An array of regions associated with the Named Flow." }
+ ],
+ "description": "This object represents a Named Flow.",
+ "hidden": true
+ },
+ {
+ "id": "PlatformFontUsage",
+ "type": "object",
+ "properties": [
+ { "name": "familyName", "type": "string", "description": "Font's family name reported by platform."},
+ { "name": "glyphCount", "type": "number", "description": "Amount of glyphs that were rendered with this font."}
+ ],
+ "description": "Information about amount of glyphs that were rendered with given font."
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables the CSS agent for the given page. Clients should not assume that the CSS agent has been enabled until the result of this command is received."
+ },
+ {
+ "name": "disable",
+ "description": "Disables the CSS agent for the given page."
+ },
+ {
+ "name": "getMatchedStylesForNode",
+ "parameters": [
+ { "name": "nodeId", "$ref": "DOM.NodeId" },
+ { "name": "includePseudo", "type": "boolean", "optional": true, "description": "Whether to include pseudo styles (default: true)." },
+ { "name": "includeInherited", "type": "boolean", "optional": true, "description": "Whether to include inherited styles (default: true)." }
+ ],
+ "returns": [
+ { "name": "matchedCSSRules", "type": "array", "items": { "$ref": "RuleMatch" }, "optional": true, "description": "CSS rules matching this node, from all applicable stylesheets." },
+ { "name": "pseudoElements", "type": "array", "items": { "$ref": "PseudoIdMatches" }, "optional": true, "description": "Pseudo style matches for this node." },
+ { "name": "inherited", "type": "array", "items": { "$ref": "InheritedStyleEntry" }, "optional": true, "description": "A chain of inherited styles (from the immediate node parent up to the DOM tree root)." }
+ ],
+ "description": "Returns requested styles for a DOM node identified by <code>nodeId</code>."
+ },
+ {
+ "name": "getInlineStylesForNode",
+ "parameters": [
+ { "name": "nodeId", "$ref": "DOM.NodeId" }
+ ],
+ "returns": [
+ { "name": "inlineStyle", "$ref": "CSSStyle", "optional": true, "description": "Inline style for the specified DOM node." },
+ { "name": "attributesStyle", "$ref": "CSSStyle", "optional": true, "description": "Attribute-defined element style (e.g. resulting from \"width=20 height=100%\")."}
+ ],
+ "description": "Returns the styles defined inline (explicitly in the \"style\" attribute and implicitly, using DOM attributes) for a DOM node identified by <code>nodeId</code>."
+ },
+ {
+ "name": "getComputedStyleForNode",
+ "parameters": [
+ { "name": "nodeId", "$ref": "DOM.NodeId" }
+ ],
+ "returns": [
+ { "name": "computedStyle", "type": "array", "items": { "$ref": "CSSComputedStyleProperty" }, "description": "Computed style for the specified DOM node." }
+ ],
+ "description": "Returns the computed style for a DOM node identified by <code>nodeId</code>."
+ },
+ {
+ "name": "getPlatformFontsForNode",
+ "parameters": [
+ { "name": "nodeId", "$ref": "DOM.NodeId" }
+ ],
+ "returns": [
+ { "name": "cssFamilyName", "type": "string", "description": "Font family name which is determined by computed style." },
+ { "name": "fonts", "type": "array", "items": { "$ref": "PlatformFontUsage"}, "description": "Usage statistics for every employed platform font." }
+ ],
+ "description": "Requests information about platform fonts which we used to render child TextNodes in the given node.",
+ "hidden": true
+ },
+ {
+ "name": "getAllStyleSheets",
+ "returns": [
+ { "name": "headers", "type": "array", "items": { "$ref": "CSSStyleSheetHeader" }, "description": "Descriptor entries for all available stylesheets." }
+ ],
+ "description": "Returns metainfo entries for all known stylesheets."
+ },
+ {
+ "name": "getStyleSheet",
+ "parameters": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId" }
+ ],
+ "returns": [
+ { "name": "styleSheet", "$ref": "CSSStyleSheetBody", "description": "Stylesheet contents for the specified <code>styleSheetId</code>." }
+ ],
+ "description": "Returns stylesheet data for the specified <code>styleSheetId</code>."
+ },
+ {
+ "name": "getStyleSheetText",
+ "parameters": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId" }
+ ],
+ "returns": [
+ { "name": "text", "type": "string", "description": "The stylesheet text." }
+ ],
+ "description": "Returns the current textual content and the URL for a stylesheet."
+ },
+ {
+ "name": "setStyleSheetText",
+ "parameters": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId" },
+ { "name": "text", "type": "string" }
+ ],
+ "description": "Sets the new stylesheet text, thereby invalidating all existing <code>CSSStyleId</code>'s and <code>CSSRuleId</code>'s contained by this stylesheet."
+ },
+ {
+ "name": "setStyleText",
+ "parameters": [
+ { "name": "styleId", "$ref": "CSSStyleId" },
+ { "name": "text", "type": "string" }
+ ],
+ "returns": [
+ { "name": "style", "$ref": "CSSStyle", "description": "The resulting style after the text modification." }
+ ],
+ "description": "Updates the CSSStyleDeclaration text."
+ },
+ {
+ "name": "setPropertyText",
+ "parameters": [
+ { "name": "styleId", "$ref": "CSSStyleId" },
+ { "name": "propertyIndex", "type": "integer" },
+ { "name": "text", "type": "string" },
+ { "name": "overwrite", "type": "boolean" }
+ ],
+ "returns": [
+ { "name": "style", "$ref": "CSSStyle", "description": "The resulting style after the property text modification." }
+ ],
+ "description": "Sets the new <code>text</code> for a property in the respective style, at offset <code>propertyIndex</code>. If <code>overwrite</code> is <code>true</code>, a property at the given offset is overwritten, otherwise inserted. <code>text</code> entirely replaces the property <code>name: value</code>."
+ },
+ {
+ "name": "toggleProperty",
+ "parameters": [
+ { "name": "styleId", "$ref": "CSSStyleId" },
+ { "name": "propertyIndex", "type": "integer" },
+ { "name": "disable", "type": "boolean" }
+ ],
+ "returns": [
+ { "name": "style", "$ref": "CSSStyle", "description": "The resulting style after the property toggling." }
+ ],
+ "description": "Toggles the property in the respective style, at offset <code>propertyIndex</code>. The <code>disable</code> parameter denotes whether the property should be disabled (i.e. removed from the style declaration). If <code>disable == false</code>, the property gets put back into its original place in the style declaration."
+ },
+ {
+ "name": "setRuleSelector",
+ "parameters": [
+ { "name": "ruleId", "$ref": "CSSRuleId" },
+ { "name": "selector", "type": "string" }
+ ],
+ "returns": [
+ { "name": "rule", "$ref": "CSSRule", "description": "The resulting rule after the selector modification." }
+ ],
+ "description": "Modifies the rule selector."
+ },
+ {
+ "name": "addRule",
+ "parameters": [
+ { "name": "contextNodeId", "$ref": "DOM.NodeId" },
+ { "name": "selector", "type": "string" }
+ ],
+ "returns": [
+ { "name": "rule", "$ref": "CSSRule", "description": "The newly created rule." }
+ ],
+ "description": "Creates a new empty rule with the given <code>selector</code> in a special \"inspector\" stylesheet in the owner document of the context node."
+ },
+ {
+ "name": "getSupportedCSSProperties",
+ "returns": [
+ { "name": "cssProperties", "type": "array", "items": { "$ref": "CSSPropertyInfo" }, "description": "Supported property metainfo." }
+ ],
+ "description": "Returns all supported CSS property names."
+ },
+ {
+ "name": "forcePseudoState",
+ "parameters": [
+ { "name": "nodeId", "$ref": "DOM.NodeId", "description": "The element id for which to force the pseudo state." },
+ { "name": "forcedPseudoClasses", "type": "array", "items": { "type": "string", "enum": ["active", "focus", "hover", "visited"] }, "description": "Element pseudo classes to force when computing the element's style." }
+ ],
+ "description": "Ensures that the given node will have specified pseudo-classes whenever its style is computed by the browser."
+ },
+ {
+ "name": "getNamedFlowCollection",
+ "parameters": [
+ { "name": "documentNodeId", "$ref": "DOM.NodeId", "description": "The document node id for which to get the Named Flow Collection." }
+ ],
+ "returns": [
+ { "name": "namedFlows", "type": "array", "items": { "$ref": "NamedFlow" }, "description": "An array containing the Named Flows in the document." }
+ ],
+ "description": "Returns the Named Flows from the document.",
+ "hidden": true
+ }
+ ],
+ "events": [
+ {
+ "name": "mediaQueryResultChanged",
+ "description": "Fires whenever a MediaQuery result changes (for example, after a browser window has been resized.) The current implementation considers only viewport-dependent media features."
+ },
+ {
+ "name": "styleSheetChanged",
+ "parameters": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId" }
+ ],
+ "description": "Fired whenever a stylesheet is changed as a result of the client operation."
+ },
+ {
+ "name": "styleSheetAdded",
+ "parameters": [
+ { "name": "header", "$ref": "CSSStyleSheetHeader", "description": "Added stylesheet metainfo." }
+ ],
+ "description": "Fired whenever an active document stylesheet is added."
+ },
+ {
+ "name": "styleSheetRemoved",
+ "parameters": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId", "description": "Identifier of the removed stylesheet." }
+ ],
+ "description": "Fired whenever an active document stylesheet is removed."
+ },
+ {
+ "name": "namedFlowCreated",
+ "parameters": [
+ { "name": "namedFlow", "$ref": "NamedFlow", "description": "The new Named Flow." }
+ ],
+ "description": "Fires when a Named Flow is created.",
+ "hidden": true
+ },
+ {
+ "name": "namedFlowRemoved",
+ "parameters": [
+ { "name": "documentNodeId", "$ref": "DOM.NodeId", "description": "The document node id." },
+ { "name": "flowName", "type": "string", "description": "Identifier of the removed Named Flow." }
+ ],
+ "description": "Fires when a Named Flow is removed: has no associated content nodes and regions.",
+ "hidden": true
+ },
+ {
+ "name": "regionLayoutUpdated",
+ "parameters": [
+ { "name": "namedFlow", "$ref": "NamedFlow", "description": "The Named Flow whose layout may have changed." }
+ ],
+ "description": "Fires when a Named Flow's layout may have changed.",
+ "hidden": true
+ },
+ {
+ "name": "regionOversetChanged",
+ "parameters": [
+ { "name": "namedFlow", "$ref": "NamedFlow", "description": "The Named Flow containing the regions whose regionOverset values changed." }
+ ],
+ "description": "Fires if any of the regionOverset values changed in a Named Flow's region chain.",
+ "hidden": true
+ }
+ ]
+ },
+ {
+ "domain": "Debugger",
+ "description": "Debugger domain exposes JavaScript debugging capabilities. It allows setting and removing breakpoints, stepping through execution, exploring stack traces, etc.",
+ "types": [
+ {
+ "id": "BreakpointId",
+ "type": "string",
+ "description": "Breakpoint identifier."
+ },
+ {
+ "id": "ScriptId",
+ "type": "string",
+ "description": "Unique script identifier."
+ },
+ {
+ "id": "CallFrameId",
+ "type": "string",
+ "description": "Call frame identifier."
+ },
+ {
+ "id": "Location",
+ "type": "object",
+ "properties": [
+ { "name": "scriptId", "$ref": "ScriptId", "description": "Script identifier as reported in the <code>Debugger.scriptParsed</code>." },
+ { "name": "lineNumber", "type": "integer", "description": "Line number in the script (0-based)." },
+ { "name": "columnNumber", "type": "integer", "optional": true, "description": "Column number in the script (0-based)." }
+ ],
+ "description": "Location in the source code."
+ },
+ {
+ "id": "FunctionDetails",
+ "hidden": true,
+ "type": "object",
+ "properties": [
+ { "name": "location", "$ref": "Location", "description": "Location of the function." },
+ { "name": "name", "type": "string", "optional": true, "description": "Name of the function. Not present for anonymous functions." },
+ { "name": "displayName", "type": "string", "optional": true, "description": "Display name of the function(specified in 'displayName' property on the function object)." },
+ { "name": "inferredName", "type": "string", "optional": true, "description": "Name of the function inferred from its initial assignment." },
+ { "name": "scopeChain", "type": "array", "optional": true, "items": { "$ref": "Scope" }, "description": "Scope chain for this closure." }
+ ],
+ "description": "Information about the function."
+ },
+ {
+ "id": "CallFrame",
+ "type": "object",
+ "properties": [
+ { "name": "callFrameId", "$ref": "CallFrameId", "description": "Call frame identifier. This identifier is only valid while the virtual machine is paused." },
+ { "name": "functionName", "type": "string", "description": "Name of the JavaScript function called on this call frame." },
+ { "name": "location", "$ref": "Location", "description": "Location in the source code." },
+ { "name": "scopeChain", "type": "array", "items": { "$ref": "Scope" }, "description": "Scope chain for this call frame." },
+ { "name": "this", "$ref": "Runtime.RemoteObject", "description": "<code>this</code> object for this call frame." }
+ ],
+ "description": "JavaScript call frame. Array of call frames form the call stack."
+ },
+ {
+ "id": "Scope",
+ "type": "object",
+ "properties": [
+ { "name": "type", "type": "string", "enum": ["global", "local", "with", "closure", "catch"], "description": "Scope type." },
+ { "name": "object", "$ref": "Runtime.RemoteObject", "description": "Object representing the scope. For <code>global</code> and <code>with</code> scopes it represents the actual object; for the rest of the scopes, it is artificial transient object enumerating scope variables as its properties." }
+ ],
+ "description": "Scope description."
+ },
+ {
+ "id": "SetScriptSourceError",
+ "type": "object",
+ "properties": [
+ { "name": "compileError", "optional": true, "type": "object", "properties":
+ [
+ { "name": "message", "type": "string", "description": "Compiler error message" },
+ { "name": "lineNumber", "type": "integer", "description": "Compile error line number (1-based)" },
+ { "name": "columnNumber", "type": "integer", "description": "Compile error column number (1-based)" }
+ ]
+ }
+ ],
+ "description": "Error data for setScriptSource command. compileError is a case type for uncompilable script source error.",
+ "hidden": true
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables debugger for the given page. Clients should not assume that the debugging has been enabled until the result for this command is received."
+ },
+ {
+ "name": "disable",
+ "description": "Disables debugger for given page."
+ },
+ {
+ "name": "setBreakpointsActive",
+ "parameters": [
+ { "name": "active", "type": "boolean", "description": "New value for breakpoints active state." }
+ ],
+ "description": "Activates / deactivates all breakpoints on the page."
+ },
+ {
+ "name": "setSkipAllPauses",
+ "hidden": true,
+ "parameters": [
+ { "name": "skipped", "type": "boolean", "description": "New value for skip pauses state." },
+ { "name": "untilReload", "type": "boolean", "optional": true, "description": "Whether page reload should set skipped to false." }
+ ],
+ "description": "Makes page not interrupt on any pauses (breakpoint, exception, dom exception etc)."
+ },
+ {
+ "name": "setBreakpointByUrl",
+ "parameters": [
+ { "name": "lineNumber", "type": "integer", "description": "Line number to set breakpoint at." },
+ { "name": "url", "type": "string", "optional": true, "description": "URL of the resources to set breakpoint on." },
+ { "name": "urlRegex", "type": "string", "optional": true, "description": "Regex pattern for the URLs of the resources to set breakpoints on. Either <code>url</code> or <code>urlRegex</code> must be specified." },
+ { "name": "columnNumber", "type": "integer", "optional": true, "description": "Offset in the line to set breakpoint at." },
+ { "name": "condition", "type": "string", "optional": true, "description": "Expression to use as a breakpoint condition. When specified, debugger will only stop on the breakpoint if this expression evaluates to true." },
+ { "name": "isAntibreakpoint", "type": "boolean", "optional": true, "hidden": true, "description": "Creates pseudo-breakpoint that prevents debugger from pausing on exception at this location." }
+ ],
+ "returns": [
+ { "name": "breakpointId", "$ref": "BreakpointId", "description": "Id of the created breakpoint for further reference." },
+ { "name": "locations", "type": "array", "items": { "$ref": "Location"}, "description": "List of the locations this breakpoint resolved into upon addition." }
+ ],
+ "description": "Sets JavaScript breakpoint at given location specified either by URL or URL regex. Once this command is issued, all existing parsed scripts will have breakpoints resolved and returned in <code>locations</code> property. Further matching script parsing will result in subsequent <code>breakpointResolved</code> events issued. This logical breakpoint will survive page reloads."
+ },
+ {
+ "name": "setBreakpoint",
+ "parameters": [
+ { "name": "location", "$ref": "Location", "description": "Location to set breakpoint in." },
+ { "name": "condition", "type": "string", "optional": true, "description": "Expression to use as a breakpoint condition. When specified, debugger will only stop on the breakpoint if this expression evaluates to true." }
+ ],
+ "returns": [
+ { "name": "breakpointId", "$ref": "BreakpointId", "description": "Id of the created breakpoint for further reference." },
+ { "name": "actualLocation", "$ref": "Location", "description": "Location this breakpoint resolved into." }
+ ],
+ "description": "Sets JavaScript breakpoint at a given location."
+ },
+ {
+ "name": "removeBreakpoint",
+ "parameters": [
+ { "name": "breakpointId", "$ref": "BreakpointId" }
+ ],
+ "description": "Removes JavaScript breakpoint."
+ },
+ {
+ "name": "continueToLocation",
+ "parameters": [
+ { "name": "location", "$ref": "Location", "description": "Location to continue to." },
+ { "name": "interstatementLocation", "type": "boolean", "optional": true, "hidden": true, "description": "Allows breakpoints at the intemediate positions inside statements." }
+ ],
+ "description": "Continues execution until specific location is reached."
+ },
+ {
+ "name": "stepOver",
+ "description": "Steps over the statement."
+ },
+ {
+ "name": "stepInto",
+ "description": "Steps into the function call."
+ },
+ {
+ "name": "stepOut",
+ "description": "Steps out of the function call."
+ },
+ {
+ "name": "pause",
+ "description": "Stops on the next JavaScript statement."
+ },
+ {
+ "name": "resume",
+ "description": "Resumes JavaScript execution."
+ },
+ {
+ "name": "searchInContent",
+ "parameters": [
+ { "name": "scriptId", "$ref": "ScriptId", "description": "Id of the script to search in." },
+ { "name": "query", "type": "string", "description": "String to search for." },
+ { "name": "caseSensitive", "type": "boolean", "optional": true, "description": "If true, search is case sensitive." },
+ { "name": "isRegex", "type": "boolean", "optional": true, "description": "If true, treats string parameter as regex." }
+ ],
+ "returns": [
+ { "name": "result", "type": "array", "items": { "$ref": "Page.SearchMatch" }, "description": "List of search matches." }
+ ],
+ "description": "Searches for given string in script content."
+ },
+ {
+ "name": "canSetScriptSource",
+ "returns": [
+ { "name": "result", "type": "boolean", "description": "True if <code>setScriptSource</code> is supported." }
+ ],
+ "description": "Always returns true."
+ },
+ {
+ "name": "setScriptSource",
+ "parameters": [
+ { "name": "scriptId", "$ref": "ScriptId", "description": "Id of the script to edit." },
+ { "name": "scriptSource", "type": "string", "description": "New content of the script." },
+ { "name": "preview", "type": "boolean", "optional": true, "description": " If true the change will not actually be applied. Preview mode may be used to get result description without actually modifying the code.", "hidden": true }
+ ],
+ "returns": [
+ { "name": "callFrames", "type": "array", "optional": true, "items": { "$ref": "CallFrame"}, "description": "New stack trace in case editing has happened while VM was stopped." },
+ { "name": "result", "type": "object", "optional": true, "description": "VM-specific description of the changes applied.", "hidden": true }
+ ],
+ "error": {
+ "$ref": "SetScriptSourceError"
+ },
+ "description": "Edits JavaScript source live."
+ },
+ {
+ "name": "restartFrame",
+ "parameters": [
+ { "name": "callFrameId", "$ref": "CallFrameId", "description": "Call frame identifier to evaluate on." }
+ ],
+ "returns": [
+ { "name": "callFrames", "type": "array", "items": { "$ref": "CallFrame"}, "description": "New stack trace." },
+ { "name": "result", "type": "object", "description": "VM-specific description.", "hidden": true }
+ ],
+ "hidden": true,
+ "description": "Restarts particular call frame from the beginning."
+ },
+ {
+ "name": "getScriptSource",
+ "parameters": [
+ { "name": "scriptId", "$ref": "ScriptId", "description": "Id of the script to get source for." }
+ ],
+ "returns": [
+ { "name": "scriptSource", "type": "string", "description": "Script source." }
+ ],
+ "description": "Returns source for the script with given id."
+ },
+ {
+ "name": "getFunctionDetails",
+ "hidden": true,
+ "parameters": [
+ { "name": "functionId", "$ref": "Runtime.RemoteObjectId", "description": "Id of the function to get location for." }
+ ],
+ "returns": [
+ { "name": "details", "$ref": "FunctionDetails", "description": "Information about the function." }
+ ],
+ "description": "Returns detailed informtation on given function."
+ },
+ {
+ "name": "setPauseOnExceptions",
+ "parameters": [
+ { "name": "state", "type": "string", "enum": ["none", "uncaught", "all"], "description": "Pause on exceptions mode." }
+ ],
+ "description": "Defines pause on exceptions state. Can be set to stop on all exceptions, uncaught exceptions or no exceptions. Initial pause on exceptions state is <code>none</code>."
+ },
+ {
+ "name": "evaluateOnCallFrame",
+ "parameters": [
+ { "name": "callFrameId", "$ref": "CallFrameId", "description": "Call frame identifier to evaluate on." },
+ { "name": "expression", "type": "string", "description": "Expression to evaluate." },
+ { "name": "objectGroup", "type": "string", "optional": true, "description": "String object group name to put result into (allows rapid releasing resulting object handles using <code>releaseObjectGroup</code>)." },
+ { "name": "includeCommandLineAPI", "type": "boolean", "optional": true, "description": "Specifies whether command line API should be available to the evaluated expression, defaults to false.", "hidden": true },
+ { "name": "doNotPauseOnExceptionsAndMuteConsole", "type": "boolean", "optional": true, "description": "Specifies whether evaluation should stop on exceptions and mute console. Overrides setPauseOnException state.", "hidden": true },
+ { "name": "returnByValue", "type": "boolean", "optional": true, "description": "Whether the result is expected to be a JSON object that should be sent by value." },
+ { "name": "generatePreview", "type": "boolean", "optional": true, "hidden": true, "description": "Whether preview should be generated for the result." }
+ ],
+ "returns": [
+ { "name": "result", "$ref": "Runtime.RemoteObject", "description": "Object wrapper for the evaluation result." },
+ { "name": "wasThrown", "type": "boolean", "optional": true, "description": "True if the result was thrown during the evaluation." }
+ ],
+ "description": "Evaluates expression on a given call frame."
+ },
+ {
+ "name": "compileScript",
+ "hidden": true,
+ "parameters": [
+ { "name": "expression", "type": "string", "description": "Expression to compile." },
+ { "name": "sourceURL", "type": "string", "description": "Source url to be set for the script." }
+ ],
+ "returns": [
+ { "name": "scriptId", "$ref": "ScriptId", "optional": true, "description": "Id of the script." },
+ { "name": "syntaxErrorMessage", "type": "string", "optional": true, "description": "Syntax error message if compilation failed." }
+ ],
+ "description": "Compiles expression."
+ },
+ {
+ "name": "runScript",
+ "hidden": true,
+ "parameters": [
+ { "name": "scriptId", "$ref": "ScriptId", "description": "Id of the script to run." },
+ { "name": "contextId", "$ref": "Runtime.ExecutionContextId", "optional": true, "description": "Specifies in which isolated context to perform script run. Each content script lives in an isolated context and this parameter may be used to specify one of those contexts. If the parameter is omitted or 0 the evaluation will be performed in the context of the inspected page." },
+ { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." },
+ { "name": "doNotPauseOnExceptionsAndMuteConsole", "type": "boolean", "optional": true, "description": "Specifies whether script run should stop on exceptions and mute console. Overrides setPauseOnException state." }
+ ],
+ "returns": [
+ { "name": "result", "$ref": "Runtime.RemoteObject", "description": "Run result." },
+ { "name": "wasThrown", "type": "boolean", "optional": true, "description": "True if the result was thrown during the script run." }
+ ],
+ "description": "Runs script with given id in a given context."
+ },
+ {
+ "name": "setOverlayMessage",
+ "parameters": [
+ { "name": "message", "type": "string", "optional": true, "description": "Overlay message to display when paused in debugger." }
+ ],
+ "hidden": true,
+ "description": "Sets overlay message."
+ },
+ {
+ "name": "setVariableValue",
+ "parameters": [
+ { "name": "scopeNumber", "type": "integer", "description": "0-based number of scope as was listed in scope chain. Only 'local', 'closure' and 'catch' scope types are allowed. Other scopes could be manipulated manually." },
+ { "name": "variableName", "type": "string", "description": "Variable name." },
+ { "name": "newValue", "$ref": "Runtime.CallArgument", "description": "New variable value." },
+ { "name": "callFrameId", "$ref": "CallFrameId", "optional": true, "description": "Id of callframe that holds variable." },
+ { "name": "functionObjectId", "$ref": "Runtime.RemoteObjectId", "optional": true, "description": "Object id of closure (function) that holds variable." }
+ ],
+ "hidden": true,
+ "description": "Changes value of variable in a callframe or a closure. Either callframe or function must be specified. Object-based scopes are not supported and must be mutated manually."
+ },
+ {
+ "name": "getStepInPositions",
+ "parameters": [
+ { "name": "callFrameId", "$ref": "CallFrameId", "description": "Id of a call frame where the current statement should be analized" }
+ ],
+ "returns": [
+ { "name": "stepInPositions", "type": "array", "items": { "$ref": "Location" }, "optional": true, "description": "experimental" }
+ ],
+ "hidden": true,
+ "description": "Lists all positions where step-in is possible for a current statement in a specified call frame"
+ },
+ {
+ "name": "getBacktrace",
+ "returns": [
+ { "name": "callFrames", "type": "array", "items": { "$ref": "CallFrame"}, "description": "Call stack the virtual machine stopped on." }
+ ],
+ "hidden": true,
+ "description": "Returns call stack including variables changed since VM was paused. VM must be paused."
+ },
+ {
+ "name": "skipStackFrames",
+ "parameters": [
+ { "name": "script", "optional": true, "type": "string", "description": "Regular expression defining the scripts to ignore while stepping." }
+ ],
+ "hidden": true,
+ "description": "Makes backend skip steps in the sources with names matching given pattern. VM will try leave blacklisted scripts by performing 'step in' several times, finally resorting to 'step out' if unsuccessful."
+ }
+ ],
+ "events": [
+ {
+ "name": "globalObjectCleared",
+ "description": "Called when global has been cleared and debugger client should reset its state. Happens upon navigation or reload."
+ },
+ {
+ "name": "scriptParsed",
+ "parameters": [
+ { "name": "scriptId", "$ref": "ScriptId", "description": "Identifier of the script parsed." },
+ { "name": "url", "type": "string", "description": "URL or name of the script parsed (if any)." },
+ { "name": "startLine", "type": "integer", "description": "Line offset of the script within the resource with given URL (for script tags)." },
+ { "name": "startColumn", "type": "integer", "description": "Column offset of the script within the resource with given URL." },
+ { "name": "endLine", "type": "integer", "description": "Last line of the script." },
+ { "name": "endColumn", "type": "integer", "description": "Length of the last line of the script." },
+ { "name": "isContentScript", "type": "boolean", "optional": true, "description": "Determines whether this script is a user extension script." },
+ { "name": "sourceMapURL", "type": "string", "optional": true, "description": "URL of source map associated with script (if any)." },
+ { "name": "hasSourceURL", "type": "boolean", "optional": true, "description": "True, if this script has sourceURL.", "hidden": true }
+ ],
+ "description": "Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger."
+ },
+ {
+ "name": "scriptFailedToParse",
+ "parameters": [
+ { "name": "scriptId", "$ref": "ScriptId", "description": "Identifier of the script parsed." },
+ { "name": "url", "type": "string", "description": "URL or name of the script parsed (if any)." },
+ { "name": "startLine", "type": "integer", "description": "Line offset of the script within the resource with given URL (for script tags)." },
+ { "name": "startColumn", "type": "integer", "description": "Column offset of the script within the resource with given URL." },
+ { "name": "endLine", "type": "integer", "description": "Last line of the script." },
+ { "name": "endColumn", "type": "integer", "description": "Length of the last line of the script." },
+ { "name": "isContentScript", "type": "boolean", "optional": true, "description": "Determines whether this script is a user extension script." },
+ { "name": "sourceMapURL", "type": "string", "optional": true, "description": "URL of source map associated with script (if any)." },
+ { "name": "hasSourceURL", "type": "boolean", "optional": true, "description": "True, if this script has sourceURL.", "hidden": true }
+ ],
+ "description": "Fired when virtual machine fails to parse the script."
+ },
+ {
+ "name": "breakpointResolved",
+ "parameters": [
+ { "name": "breakpointId", "$ref": "BreakpointId", "description": "Breakpoint unique identifier." },
+ { "name": "location", "$ref": "Location", "description": "Actual breakpoint location." }
+ ],
+ "description": "Fired when breakpoint is resolved to an actual script and location."
+ },
+ {
+ "name": "paused",
+ "parameters": [
+ { "name": "callFrames", "type": "array", "items": { "$ref": "CallFrame" }, "description": "Call stack the virtual machine stopped on." },
+ { "name": "reason", "type": "string", "enum": [ "XHR", "DOM", "EventListener", "exception", "assert", "CSPViolation", "debugCommand", "other" ], "description": "Pause reason." },
+ { "name": "data", "type": "object", "optional": true, "description": "Object containing break-specific auxiliary properties." },
+ { "name": "hitBreakpoints", "type": "array", "optional": true, "items": { "type": "string" }, "description": "Hit breakpoints IDs", "hidden": true }
+ ],
+ "description": "Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria."
+ },
+ {
+ "name": "resumed",
+ "description": "Fired when the virtual machine resumed execution."
+ }
+ ]
+ },
+ {
+ "domain": "DOMDebugger",
+ "description": "DOM debugging allows setting breakpoints on particular DOM operations and events. JavaScript execution will stop on these operations as if there was a regular breakpoint set.",
+ "types": [
+ {
+ "id": "DOMBreakpointType",
+ "type": "string",
+ "enum": ["subtree-modified", "attribute-modified", "node-removed"],
+ "description": "DOM breakpoint type."
+ }
+ ],
+ "commands": [
+ {
+ "name": "setDOMBreakpoint",
+ "parameters": [
+ { "name": "nodeId", "$ref": "DOM.NodeId", "description": "Identifier of the node to set breakpoint on." },
+ { "name": "type", "$ref": "DOMBreakpointType", "description": "Type of the operation to stop upon." }
+ ],
+ "description": "Sets breakpoint on particular operation with DOM."
+ },
+ {
+ "name": "removeDOMBreakpoint",
+ "parameters": [
+ { "name": "nodeId", "$ref": "DOM.NodeId", "description": "Identifier of the node to remove breakpoint from." },
+ { "name": "type", "$ref": "DOMBreakpointType", "description": "Type of the breakpoint to remove." }
+ ],
+ "description": "Removes DOM breakpoint that was set using <code>setDOMBreakpoint</code>."
+ },
+ {
+ "name": "setEventListenerBreakpoint",
+ "parameters": [
+ { "name": "eventName", "type": "string", "description": "DOM Event name to stop on (any DOM event will do)." }
+ ],
+ "description": "Sets breakpoint on particular DOM event."
+ },
+ {
+ "name": "removeEventListenerBreakpoint",
+ "parameters": [
+ { "name": "eventName", "type": "string", "description": "Event name." }
+ ],
+ "description": "Removes breakpoint on particular DOM event."
+ },
+ {
+ "name": "setInstrumentationBreakpoint",
+ "parameters": [
+ { "name": "eventName", "type": "string", "description": "Instrumentation name to stop on." }
+ ],
+ "description": "Sets breakpoint on particular native event.",
+ "hidden": true
+ },
+ {
+ "name": "removeInstrumentationBreakpoint",
+ "parameters": [
+ { "name": "eventName", "type": "string", "description": "Instrumentation name to stop on." }
+ ],
+ "description": "Removes breakpoint on particular native event.",
+ "hidden": true
+ },
+ {
+ "name": "setXHRBreakpoint",
+ "parameters": [
+ { "name": "url", "type": "string", "description": "Resource URL substring. All XHRs having this substring in the URL will get stopped upon." }
+ ],
+ "description": "Sets breakpoint on XMLHttpRequest."
+ },
+ {
+ "name": "removeXHRBreakpoint",
+ "parameters": [
+ { "name": "url", "type": "string", "description": "Resource URL substring." }
+ ],
+ "description": "Removes breakpoint from XMLHttpRequest."
+ }
+ ]
+ },
+ {
+ "domain": "Profiler",
+ "hidden": true,
+ "types": [
+ {
+ "id": "ProfileHeader",
+ "type": "object",
+ "description": "Profile header.",
+ "properties": [
+ { "name": "title", "type": "string", "description": "Profile title." },
+ { "name": "uid", "type": "integer", "description": "Unique identifier of the profile." }
+ ]
+ },
+ {
+ "id": "CPUProfileNode",
+ "type": "object",
+ "description": "CPU Profile node. Holds callsite information, execution statistics and child nodes.",
+ "properties": [
+ { "name": "functionName", "type": "string", "description": "Function name." },
+ { "name": "scriptId", "$ref": "Debugger.ScriptId", "description": "Script identifier." },
+ { "name": "url", "type": "string", "description": "URL." },
+ { "name": "lineNumber", "type": "integer", "description": "Line number." },
+ { "name": "hitCount", "type": "integer", "description": "Number of samples where this node was on top of the call stack." },
+ { "name": "callUID", "type": "number", "description": "Call UID." },
+ { "name": "children", "type": "array", "items": { "$ref": "CPUProfileNode" }, "description": "Child nodes." },
+ { "name": "deoptReason", "type": "string", "description": "The reason of being not optimized. The function may be deoptimized or marked as don't optimize."},
+ { "name": "id", "optional": true, "type": "integer", "description": "Unique id of the node." }
+ ]
+ },
+ {
+ "id": "CPUProfile",
+ "type": "object",
+ "description": "Profile.",
+ "properties": [
+ { "name": "head", "$ref": "CPUProfileNode" },
+ { "name": "startTime", "type": "number", "description": "Profiling start time in seconds." },
+ { "name": "endTime", "type": "number", "description": "Profiling end time in seconds." },
+ { "name": "samples", "optional": true, "type": "array", "items": { "type": "integer" }, "description": "Ids of samples top nodes." }
+ ]
+ },
+ {
+ "id": "HeapSnapshotObjectId",
+ "type": "string",
+ "description": "Heap snashot object id."
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable"
+ },
+ {
+ "name": "disable"
+ },
+ {
+ "name": "start"
+ },
+ {
+ "name": "stop",
+ "returns": [
+ { "name": "header", "$ref": "ProfileHeader", "description": "The header of the recorded profile."}
+ ]
+ },
+ {
+ "name": "getProfileHeaders",
+ "returns": [
+ { "name": "headers", "type": "array", "items": { "$ref": "ProfileHeader"} }
+ ]
+ },
+ {
+ "name": "getCPUProfile",
+ "parameters": [
+ { "name": "uid", "type": "integer" }
+ ],
+ "returns": [
+ { "name": "profile", "$ref": "CPUProfile" }
+ ]
+ },
+ {
+ "name": "removeProfile",
+ "parameters": [
+ { "name": "type", "type": "string" },
+ { "name": "uid", "type": "integer" }
+ ]
+ },
+ {
+ "name": "clearProfiles"
+ }
+ ],
+ "events": [
+ {
+ "name": "addProfileHeader",
+ "parameters": [
+ { "name": "header", "$ref": "ProfileHeader" }
+ ]
+ },
+ {
+ "name": "setRecordingProfile",
+ "parameters": [
+ { "name": "isProfiling", "type": "boolean" }
+ ]
+ },
+ {
+ "name": "resetProfiles"
+ }
+ ]
+ },
+ {
+ "domain": "HeapProfiler",
+ "hidden": true,
+ "types": [
+ {
+ "id": "ProfileHeader",
+ "type": "object",
+ "description": "Profile header.",
+ "properties": [
+ { "name": "title", "type": "string", "description": "Profile title." },
+ { "name": "uid", "type": "integer", "description": "Unique identifier of the profile." },
+ { "name": "maxJSObjectId", "type": "integer", "optional": true, "description": "Last seen JS object Id." }
+ ]
+ },
+ {
+ "id": "HeapSnapshotObjectId",
+ "type": "string",
+ "description": "Heap snashot object id."
+ }
+ ],
+ "commands": [
+ {
+ "name": "getProfileHeaders",
+ "returns": [
+ { "name": "headers", "type": "array", "items": { "$ref": "ProfileHeader"} }
+ ]
+ },
+ {
+ "name": "startTrackingHeapObjects"
+ },
+ {
+ "name": "stopTrackingHeapObjects"
+ },
+ {
+ "name": "getHeapSnapshot",
+ "parameters": [
+ { "name": "uid", "type": "integer" }
+ ]
+ },
+ {
+ "name": "removeProfile",
+ "parameters": [
+ { "name": "uid", "type": "integer" }
+ ]
+ },
+ {
+ "name": "clearProfiles"
+ },
+ {
+ "name": "takeHeapSnapshot",
+ "parameters": [
+ { "name": "reportProgress", "type": "boolean", "optional": true, "description": "If true 'reportHeapSnapshotProgress' events will be generated while snapshot is being taken." }
+ ]
+ },
+ {
+ "name": "collectGarbage"
+ },
+ {
+ "name": "getObjectByHeapObjectId",
+ "parameters": [
+ { "name": "objectId", "$ref": "HeapSnapshotObjectId" },
+ { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." }
+ ],
+ "returns": [
+ { "name": "result", "$ref": "Runtime.RemoteObject", "description": "Evaluation result." }
+ ]
+ },
+ {
+ "name": "getHeapObjectId",
+ "parameters": [
+ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "Identifier of the object to get heap object id for." }
+ ],
+ "returns": [
+ { "name": "heapSnapshotObjectId", "$ref": "HeapSnapshotObjectId", "description": "Id of the heap snapshot object corresponding to the passed remote object id." }
+ ]
+ }
+ ],
+ "events": [
+ {
+ "name": "addProfileHeader",
+ "parameters": [
+ { "name": "header", "$ref": "ProfileHeader" }
+ ]
+ },
+ {
+ "name": "addHeapSnapshotChunk",
+ "parameters": [
+ { "name": "uid", "type": "integer" },
+ { "name": "chunk", "type": "string" }
+ ]
+ },
+ {
+ "name": "finishHeapSnapshot",
+ "parameters": [
+ { "name": "uid", "type": "integer" }
+ ]
+ },
+ {
+ "name": "resetProfiles"
+ },
+ {
+ "name": "reportHeapSnapshotProgress",
+ "parameters": [
+ { "name": "done", "type": "integer" },
+ { "name": "total", "type": "integer" }
+ ]
+ },
+ {
+ "name": "lastSeenObjectId",
+ "description": "If heap objects tracking has been started then backend regulary sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event.",
+ "parameters": [
+ { "name": "lastSeenObjectId", "type": "integer" },
+ { "name": "timestamp", "type": "number" }
+ ]
+ },
+ {
+ "name": "heapStatsUpdate",
+ "description": "If heap objects tracking has been started then backend may send update for one or more fragments",
+ "parameters": [
+ { "name": "statsUpdate", "type": "array", "items": { "type": "integer" }, "description": "An array of triplets. Each triplet describes a fragment. The first integer is the fragment index, the second integer is a total count of objects for the fragment, the third integer is a total size of the objects for the fragment."}
+ ]
+ }
+ ]
+ },
+ {
+ "domain": "Worker",
+ "hidden": true,
+ "types": [],
+ "commands": [
+ {
+ "name": "enable"
+ },
+ {
+ "name": "disable"
+ },
+ {
+ "name": "sendMessageToWorker",
+ "parameters": [
+ { "name": "workerId", "type": "integer" },
+ { "name": "message", "type": "object" }
+ ]
+ },
+ {
+ "name": "canInspectWorkers",
+ "description": "Tells whether browser supports workers inspection.",
+ "returns": [
+ { "name": "result", "type": "boolean", "description": "True if browser has workers support." }
+ ]
+ },
+ {
+ "name": "connectToWorker",
+ "parameters": [
+ { "name": "workerId", "type": "integer" }
+ ]
+ },
+ {
+ "name": "disconnectFromWorker",
+ "parameters": [
+ { "name": "workerId", "type": "integer" }
+ ]
+ },
+ {
+ "name": "setAutoconnectToWorkers",
+ "parameters": [
+ { "name": "value", "type": "boolean" }
+ ]
+ }
+ ],
+ "events": [
+ {
+ "name": "workerCreated",
+ "parameters": [
+ { "name": "workerId", "type": "integer" },
+ { "name": "url", "type": "string" },
+ { "name": "inspectorConnected", "type": "boolean" }
+ ]
+ },
+ {
+ "name": "workerTerminated",
+ "parameters": [
+ { "name": "workerId", "type": "integer" }
+ ]
+ },
+ {
+ "name": "dispatchMessageFromWorker",
+ "parameters": [
+ { "name": "workerId", "type": "integer" },
+ { "name": "message", "type": "object" }
+ ]
+ },
+ {
+ "name": "disconnectedFromWorker"
+ }
+ ]
+ },
+ {
+ "domain": "Canvas",
+ "hidden": true,
+ "types": [
+ {
+ "id": "ResourceId",
+ "type": "string",
+ "description": "Unique resource identifier."
+ },
+ {
+ "id": "ResourceStateDescriptor",
+ "type": "object",
+ "description": "Resource state descriptor.",
+ "properties": [
+ { "name": "name", "type": "string", "description": "State name." },
+ { "name": "enumValueForName", "type": "string", "optional": true, "description": "String representation of the enum value, if <code>name</code> stands for an enum." },
+ { "name": "value", "$ref": "CallArgument", "optional": true, "description": "The value associated with the particular state." },
+ { "name": "values", "type": "array", "items": { "$ref": "ResourceStateDescriptor" }, "optional": true, "description": "Array of values associated with the particular state. Either <code>value</code> or <code>values</code> will be specified." },
+ { "name": "isArray", "type": "boolean", "optional": true, "description": "True iff the given <code>values</code> items stand for an array rather than a list of grouped states." }
+ ]
+ },
+ {
+ "id": "ResourceState",
+ "type": "object",
+ "description": "Resource state.",
+ "properties": [
+ { "name": "id", "$ref": "ResourceId" },
+ { "name": "traceLogId", "$ref": "TraceLogId" },
+ { "name": "descriptors", "type": "array", "items": { "$ref": "ResourceStateDescriptor" }, "optional": true, "description": "Describes current <code>Resource</code> state." },
+ { "name": "imageURL", "type": "string", "optional": true, "description": "Screenshot image data URL." }
+ ]
+ },
+ {
+ "id": "CallArgument",
+ "type": "object",
+ "properties": [
+ { "name": "description", "type": "string", "description": "String representation of the object." },
+ { "name": "enumName", "type": "string", "optional": true, "description": "Enum name, if any, that stands for the value (for example, a WebGL enum name)." },
+ { "name": "resourceId", "$ref": "ResourceId", "optional": true, "description": "Resource identifier. Specified for <code>Resource</code> objects only." },
+ { "name": "type", "type": "string", "optional": true, "enum": ["object", "function", "undefined", "string", "number", "boolean"], "description": "Object type. Specified for non <code>Resource</code> objects only." },
+ { "name": "subtype", "type": "string", "optional": true, "enum": ["array", "null", "node", "regexp", "date"], "description": "Object subtype hint. Specified for <code>object</code> type values only." },
+ { "name": "remoteObject", "$ref": "Runtime.RemoteObject", "optional": true, "description": "The <code>RemoteObject</code>, if requested." }
+ ]
+ },
+ {
+ "id": "Call",
+ "type": "object",
+ "properties": [
+ { "name": "contextId", "$ref": "ResourceId" },
+ { "name": "functionName", "type": "string", "optional": true },
+ { "name": "arguments", "type": "array", "items": { "$ref": "CallArgument" }, "optional": true },
+ { "name": "result", "$ref": "CallArgument", "optional": true },
+ { "name": "isDrawingCall", "type": "boolean", "optional": true },
+ { "name": "isFrameEndCall", "type": "boolean", "optional": true },
+ { "name": "property", "type": "string", "optional": true },
+ { "name": "value", "$ref": "CallArgument", "optional": true },
+ { "name": "sourceURL", "type": "string", "optional": true },
+ { "name": "lineNumber", "type": "integer", "optional": true },
+ { "name": "columnNumber", "type": "integer", "optional": true }
+ ]
+ },
+ {
+ "id": "TraceLogId",
+ "type": "string",
+ "description": "Unique trace log identifier."
+ },
+ {
+ "id": "TraceLog",
+ "type": "object",
+ "properties": [
+ { "name": "id", "$ref": "TraceLogId" },
+ { "name": "calls", "type": "array", "items": { "$ref": "Call" } },
+ { "name": "contexts", "type": "array", "items": { "$ref": "CallArgument" } },
+ { "name": "startOffset", "type": "integer" },
+ { "name": "alive", "type": "boolean" },
+ { "name": "totalAvailableCalls", "type": "number" }
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables Canvas inspection."
+ },
+ {
+ "name": "disable",
+ "description": "Disables Canvas inspection."
+ },
+ {
+ "name": "dropTraceLog",
+ "parameters": [
+ { "name": "traceLogId", "$ref": "TraceLogId" }
+ ]
+ },
+ {
+ "name": "hasUninstrumentedCanvases",
+ "returns": [
+ { "name": "result", "type": "boolean" }
+ ],
+ "description": "Checks if there is any uninstrumented canvas in the inspected page."
+ },
+ {
+ "name": "captureFrame",
+ "parameters": [
+ { "name": "frameId", "$ref": "Page.FrameId", "optional": true, "description": "Identifier of the frame containing document whose canvases are to be captured. If omitted, main frame is assumed." }
+ ],
+ "returns": [
+ { "name": "traceLogId", "$ref": "TraceLogId", "description": "Identifier of the trace log containing captured canvas calls." }
+ ],
+ "description": "Starts (or continues) a canvas frame capturing which will be stopped automatically after the next frame is prepared."
+ },
+ {
+ "name": "startCapturing",
+ "parameters": [
+ { "name": "frameId", "$ref": "Page.FrameId", "optional": true, "description": "Identifier of the frame containing document whose canvases are to be captured. If omitted, main frame is assumed." }
+ ],
+ "returns": [
+ { "name": "traceLogId", "$ref": "TraceLogId", "description": "Identifier of the trace log containing captured canvas calls." }
+ ],
+ "description": "Starts (or continues) consecutive canvas frames capturing. The capturing is stopped by the corresponding stopCapturing command."
+ },
+ {
+ "name": "stopCapturing",
+ "parameters": [
+ { "name": "traceLogId", "$ref": "TraceLogId" }
+ ]
+ },
+ {
+ "name": "getTraceLog",
+ "parameters": [
+ { "name": "traceLogId", "$ref": "TraceLogId" },
+ { "name": "startOffset", "type": "integer", "optional": true },
+ { "name": "maxLength", "type": "integer", "optional": true }
+ ],
+ "returns": [
+ { "name": "traceLog", "$ref": "TraceLog" }
+ ]
+ },
+ {
+ "name": "replayTraceLog",
+ "parameters": [
+ { "name": "traceLogId", "$ref": "TraceLogId" },
+ { "name": "stepNo", "type": "integer", "description": "Last call index in the trace log to replay (zero based)." }
+ ],
+ "returns": [
+ { "name": "resourceState", "$ref": "ResourceState" },
+ { "name": "replayTime", "type": "number", "description": "Replay time (in milliseconds)." }
+ ]
+ },
+ {
+ "name": "getResourceState",
+ "parameters": [
+ { "name": "traceLogId", "$ref": "TraceLogId" },
+ { "name": "resourceId", "$ref": "ResourceId" }
+ ],
+ "returns": [
+ { "name": "resourceState", "$ref": "ResourceState" }
+ ]
+ },
+ {
+ "name": "evaluateTraceLogCallArgument",
+ "parameters": [
+ { "name": "traceLogId", "$ref": "TraceLogId" },
+ { "name": "callIndex", "type": "integer", "description": "Index of the call to evaluate on (zero based)." },
+ { "name": "argumentIndex", "type": "integer", "description": "Index of the argument to evaluate (zero based). Provide <code>-1</code> to evaluate call result." },
+ { "name": "objectGroup", "type": "string", "optional": true, "description": "String object group name to put result into (allows rapid releasing resulting object handles using <code>Runtime.releaseObjectGroup</code>)." }
+ ],
+ "returns": [
+ { "name": "result", "$ref": "Runtime.RemoteObject", "optional": true, "description": "Object wrapper for the evaluation result." },
+ { "name": "resourceState", "$ref": "ResourceState", "optional": true, "description": "State of the <code>Resource</code> object." }
+ ],
+ "description": "Evaluates a given trace call argument or its result."
+ }
+ ],
+ "events": [
+ {
+ "name": "contextCreated",
+ "parameters": [
+ { "name": "frameId", "$ref": "Page.FrameId", "description": "Identifier of the frame containing a canvas with a context." }
+ ],
+ "description": "Fired when a canvas context has been created in the given frame. The context may not be instrumented (see hasUninstrumentedCanvases command)."
+ },
+ {
+ "name": "traceLogsRemoved",
+ "parameters": [
+ { "name": "frameId", "$ref": "Page.FrameId", "optional": true, "description": "If given, trace logs from the given frame were removed." },
+ { "name": "traceLogId", "$ref": "TraceLogId", "optional": true, "description": "If given, trace log with the given ID was removed." }
+ ],
+ "description": "Fired when a set of trace logs were removed from the backend. If no parameters are given, all trace logs were removed."
+ }
+ ]
+ },
+ {
+ "domain": "Input",
+ "types": [
+ {
+ "id": "TouchPoint",
+ "type": "object",
+ "hidden": true,
+ "properties": [
+ { "name": "state", "type": "string", "enum": ["touchPressed", "touchReleased", "touchMoved", "touchStationary", "touchCancelled"], "description": "State of the touch point." },
+ { "name": "x", "type": "integer", "description": "X coordinate of the event relative to the main frame's viewport."},
+ { "name": "y", "type": "integer", "description": "Y coordinate of the event relative to the main frame's viewport. 0 refers to the top of the viewport and Y increases as it proceeds towards the bottom of the viewport."},
+ { "name": "radiusX", "type": "integer", "optional": true, "description": "X radius of the touch area (default: 1)."},
+ { "name": "radiusY", "type": "integer", "optional": true, "description": "Y radius of the touch area (default: 1)."},
+ { "name": "rotationAngle", "type": "number", "optional": true, "description": "Rotation angle (default: 0.0)."},
+ { "name": "force", "type": "number", "optional": true, "description": "Force (default: 1.0)."},
+ { "name": "id", "type": "number", "optional": true, "description": "Identifier used to track touch sources between events, must be unique within an event."}
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "dispatchKeyEvent",
+ "parameters": [
+ { "name": "type", "type": "string", "enum": ["keyDown", "keyUp", "rawKeyDown", "char"], "description": "Type of the key event." },
+ { "name": "modifiers", "type": "integer", "optional": true, "description": "Bit field representing pressed modifier keys. Alt=1, Ctrl=2, Meta/Command=4, Shift=8 (default: 0)." },
+ { "name": "timestamp", "type": "number", "optional": true, "description": "Time at which the event occurred. Measured in UTC time in seconds since January 1, 1970 (default: current time)." },
+ { "name": "text", "type": "string", "optional": true, "description": "Text as generated by processing a virtual key code with a keyboard layout. Not needed for for <code>keyUp</code> and <code>rawKeyDown</code> events (default: \"\")" },
+ { "name": "unmodifiedText", "type": "string", "optional": true, "description": "Text that would have been generated by the keyboard if no modifiers were pressed (except for shift). Useful for shortcut (accelerator) key handling (default: \"\")." },
+ { "name": "keyIdentifier", "type": "string", "optional": true, "description": "Unique key identifier (e.g., 'U+0041') (default: \"\")." },
+ { "name": "windowsVirtualKeyCode", "type": "integer", "optional": true, "description": "Windows virtual key code (default: 0)." },
+ { "name": "nativeVirtualKeyCode", "type": "integer", "optional": true, "description": "Native virtual key code (default: 0)." },
+ { "name": "autoRepeat", "type": "boolean", "optional": true, "description": "Whether the event was generated from auto repeat (default: false)." },
+ { "name": "isKeypad", "type": "boolean", "optional": true, "description": "Whether the event was generated from the keypad (default: false)." },
+ { "name": "isSystemKey", "type": "boolean", "optional": true, "description": "Whether the event was a system key event (default: false)." }
+ ],
+ "description": "Dispatches a key event to the page."
+ },
+ {
+ "name": "dispatchMouseEvent",
+ "parameters": [
+ { "name": "type", "type": "string", "enum": ["mousePressed", "mouseReleased", "mouseMoved"], "description": "Type of the mouse event." },
+ { "name": "x", "type": "integer", "description": "X coordinate of the event relative to the main frame's viewport."},
+ { "name": "y", "type": "integer", "description": "Y coordinate of the event relative to the main frame's viewport. 0 refers to the top of the viewport and Y increases as it proceeds towards the bottom of the viewport."},
+ { "name": "modifiers", "type": "integer", "optional": true, "description": "Bit field representing pressed modifier keys. Alt=1, Ctrl=2, Meta/Command=4, Shift=8 (default: 0)." },
+ { "name": "timestamp", "type": "number", "optional": true, "description": "Time at which the event occurred. Measured in UTC time in seconds since January 1, 1970 (default: current time)." },
+ { "name": "button", "type": "string", "enum": ["none", "left", "middle", "right"], "optional": true, "description": "Mouse button (default: \"none\")." },
+ { "name": "clickCount", "type": "integer", "optional": true, "description": "Number of times the mouse button was clicked (default: 0)." },
+ { "name": "deviceSpace", "type": "boolean", "optional": true, "hidden": true, "description": "If true, x and y are given in dip wrt current viewport." }
+ ],
+ "description": "Dispatches a mouse event to the page."
+ },
+ {
+ "name": "dispatchTouchEvent",
+ "hidden": true,
+ "parameters": [
+ { "name": "type", "type": "string", "enum": ["touchStart", "touchEnd", "touchMove"], "description": "Type of the touch event." },
+ { "name": "touchPoints", "type": "array", "items": { "$ref": "TouchPoint" }, "description": "Touch points." },
+ { "name": "modifiers", "type": "integer", "optional": true, "description": "Bit field representing pressed modifier keys. Alt=1, Ctrl=2, Meta/Command=4, Shift=8 (default: 0)." },
+ { "name": "timestamp", "type": "number", "optional": true, "description": "Time at which the event occurred. Measured in UTC time in seconds since January 1, 1970 (default: current time)." }
+ ],
+ "description": "Dispatches a touch event to the page."
+ },
+ {
+ "name": "dispatchGestureEvent",
+ "hidden": true,
+ "parameters": [
+ { "name": "type", "type": "string", "enum": ["scrollBegin", "scrollEnd", "scrollUpdate", "tapDown", "tap", "pinchBegin", "pinchEnd", "pinchUpdate"], "description": "Type of the gesture event." },
+ { "name": "x", "type": "integer", "description": "X coordinate relative to the screen's viewport."},
+ { "name": "y", "type": "integer", "description": "Y coordinate relative to the screen's viewport."},
+ { "name": "timestamp", "type": "number", "optional": true, "description": "Time at which the event occurred. Measured in UTC time in seconds since January 1, 1970 (default: current time)." },
+ { "name": "deltaX", "type": "integer", "optional": true, "description": "Delta X where apllies."},
+ { "name": "deltaY", "type": "integer", "optional": true, "description": "Delta Y where apllies."},
+ { "name": "pinchScale", "type": "number", "optional": true, "description": "Pinch scale." }
+ ],
+ "description": "Dispatches a gesture event to the page."
+ }
+ ],
+ "events": []
+ },
+ {
+ "domain": "LayerTree",
+ "hidden": true,
+ "types": [
+ {
+ "id": "LayerId",
+ "type": "string",
+ "description": "Unique Layer identifier."
+ },
+ {
+ "id": "Layer",
+ "type": "object",
+ "description": "Information about a compositing layer.",
+ "properties": [
+ { "name": "layerId", "$ref": "LayerId", "description": "The unique id for this layer." },
+ { "name": "parentLayerId", "$ref": "LayerId", "optional": true, "description": "The id of parent (not present for root)." },
+ { "name": "nodeId", "$ref": "DOM.NodeId", "optional": true, "description": "The id for the node associated with this layer." },
+ { "name": "offsetX", "type": "number", "description": "Offset from parent layer, X coordinate." },
+ { "name": "offsetY", "type": "number", "description": "Offset from parent layer, X coordinate." },
+ { "name": "width", "type": "number", "description": "Layer width." },
+ { "name": "height", "type": "number", "description": "Layer height." },
+ { "name": "transform", "type": "array", "items": { "type": "number" }, "minItems": 16, "maxItems": 16, "optional": true, "description": "Transformation matrix for layer, default is identity matrix" },
+ { "name": "anchorX", "type": "number", "optional": true, "description": "Transform anchor point X, absent if no transform specified" },
+ { "name": "anchorY", "type": "number", "optional": true, "description": "Transform anchor point Y, absent if no transform specified" },
+ { "name": "anchorZ", "type": "number", "optional": true, "description": "Transform anchor point Z, absent if no transform specified" },
+ { "name": "paintCount", "type": "integer", "description": "Indicates how many time this layer has painted." },
+ { "name": "invisible", "type": "boolean", "optional": true, "description": "Set if layer is not visible." }
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables compositing tree inspection."
+ },
+ {
+ "name": "disable",
+ "description": "Disables compositing tree inspection."
+ },
+ {
+ "name": "getLayers",
+ "parameters": [
+ { "name": "nodeId", "optional": true, "$ref": "DOM.NodeId", "description": "Root of the subtree for which we want to gather layers (return entire tree if not specified)" }
+ ],
+ "description": "Returns the layer tree structure of the current page.",
+ "returns": [
+ { "name": "layers", "type": "array", "items": { "$ref": "Layer" }, "description": "Child layers." }
+ ]
+ },
+ {
+ "name": "compositingReasons",
+ "parameters": [
+ { "name": "layerId", "$ref": "LayerId", "description": "The id of the layer for which we want to get the reasons it was composited." }
+ ],
+ "description": "Provides the reasons why the given layer was composited.",
+ "returns": [
+ { "name": "compositingReasons", "type": "array", "items": { "type": "string" }, "description": "A list of strings specifying reasons for the given layer to become composited." }
+ ]
+ }
+ ],
+ "events": [
+ {
+ "name": "layerTreeDidChange"
+ }
+ ]
+ },
+ {
+ "domain": "Tracing",
+ "hidden": true,
+ "commands": [
+ {
+ "name": "start",
+ "description": "Strart trace events collection.",
+ "parameters": [
+ { "name": "categories", "type": "string", "description": "Category/tag filter" }
+ ]
+ },
+ {
+ "name": "end",
+ "description": "Stop trace events collection."
+ }
+ ],
+ "events": [
+ {
+ "name": "dataCollected",
+ "parameters": [
+ { "name": "value", "type": "array", "items": { "type": "object" } }
+ ]
+ },
+ {
+ "name": "tracingComplete"
+ }
+ ]
+ }]
+}
diff --git a/deps/v8_inspector/devtools/protocol.json b/deps/v8_inspector/devtools/protocol.json
new file mode 100644
index 0000000000..213274bd7c
--- /dev/null
+++ b/deps/v8_inspector/devtools/protocol.json
@@ -0,0 +1,5167 @@
+{
+ "version": { "major": "1", "minor": "1" },
+ "domains": [{
+ "domain": "Inspector",
+ "hidden": true,
+ "types": [],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables inspector domain notifications.",
+ "handlers": ["browser"]
+ },
+ {
+ "name": "disable",
+ "description": "Disables inspector domain notifications.",
+ "handlers": ["browser"]
+ }
+ ],
+ "events": [
+ {
+ "name": "detached",
+ "description": "Fired when remote debugging connection is about to be terminated. Contains detach reason.",
+ "parameters": [
+ { "name": "reason", "type": "string", "description": "The reason why connection has been terminated." }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "targetCrashed",
+ "description": "Fired when debugging target has crashed",
+ "handlers": ["browser"]
+ }
+ ]
+ },
+ {
+ "domain": "Memory",
+ "hidden": true,
+ "types": [
+ {
+ "id": "PressureLevel",
+ "type": "string",
+ "enum": ["moderate", "critical"],
+ "description": "Memory pressure level."
+ }
+ ],
+ "commands": [
+ {
+ "name": "getDOMCounters",
+ "returns": [
+ { "name": "documents", "type": "integer" },
+ { "name": "nodes", "type": "integer" },
+ { "name": "jsEventListeners", "type": "integer" }
+ ]
+ },
+ {
+ "name": "setPressureNotificationsSuppressed",
+ "description": "Enable/disable suppressing memory pressure notifications in all processes.",
+ "parameters": [
+ { "name": "suppressed", "type": "boolean", "description": "If true, memory pressure notifications will be suppressed."}
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "simulatePressureNotification",
+ "description": "Simulate a memory pressure notification in all processes.",
+ "parameters": [
+ { "name": "level", "$ref": "PressureLevel", "description": "Memory pressure level of the notification." }
+ ],
+ "handlers": ["browser"]
+ }
+ ]
+ },
+ {
+ "domain": "Page",
+ "description": "Actions and events related to the inspected page belong to the page domain.",
+ "types": [
+ {
+ "id": "ResourceType",
+ "type": "string",
+ "enum": ["Document", "Stylesheet", "Image", "Media", "Font", "Script", "TextTrack", "XHR", "Fetch", "EventSource", "WebSocket", "Manifest", "Other"],
+ "description": "Resource type as it was perceived by the rendering engine."
+ },
+ {
+ "id": "FrameId",
+ "type": "string",
+ "description": "Unique frame identifier."
+ },
+ {
+ "id": "Frame",
+ "type": "object",
+ "description": "Information about the Frame on the page.",
+ "properties": [
+ { "name": "id", "type": "string", "description": "Frame unique identifier." },
+ { "name": "parentId", "type": "string", "optional": true, "description": "Parent frame identifier." },
+ { "name": "loaderId", "$ref": "Network.LoaderId", "description": "Identifier of the loader associated with this frame." },
+ { "name": "name", "type": "string", "optional": true, "description": "Frame's name as specified in the tag." },
+ { "name": "url", "type": "string", "description": "Frame document's URL." },
+ { "name": "securityOrigin", "type": "string", "description": "Frame document's security origin." },
+ { "name": "mimeType", "type": "string", "description": "Frame document's mimeType as determined by the browser." }
+ ]
+ },
+ {
+ "id": "FrameResource",
+ "type": "object",
+ "description": "Information about the Resource on the page.",
+ "properties": [
+ { "name": "url", "type": "string", "description": "Resource URL." },
+ { "name": "type", "$ref": "ResourceType", "description": "Type of this resource." },
+ { "name": "mimeType", "type": "string", "description": "Resource mimeType as determined by the browser." },
+ { "name": "failed", "type": "boolean", "optional": true, "description": "True if the resource failed to load." },
+ { "name": "canceled", "type": "boolean", "optional": true, "description": "True if the resource was canceled during loading." }
+ ],
+ "hidden": true
+ },
+ {
+ "id": "FrameResourceTree",
+ "type": "object",
+ "description": "Information about the Frame hierarchy along with their cached resources.",
+ "properties": [
+ { "name": "frame", "$ref": "Frame", "description": "Frame information for this tree item." },
+ { "name": "childFrames", "type": "array", "optional": true, "items": { "$ref": "FrameResourceTree" }, "description": "Child frames." },
+ { "name": "resources", "type": "array", "items": { "$ref": "FrameResource" }, "description": "Information about frame resources." }
+ ],
+ "hidden": true
+ },
+ {
+ "id": "ScriptIdentifier",
+ "type": "string",
+ "description": "Unique script identifier.",
+ "hidden": true
+ },
+ {
+ "id": "NavigationEntry",
+ "type": "object",
+ "description": "Navigation history entry.",
+ "properties": [
+ { "name": "id", "type": "integer", "description": "Unique id of the navigation history entry." },
+ { "name": "url", "type": "string", "description": "URL of the navigation history entry." },
+ { "name": "title", "type": "string", "description": "Title of the navigation history entry." }
+ ],
+ "hidden": true
+ },
+ {
+ "id": "ScreencastFrameMetadata",
+ "type": "object",
+ "description": "Screencast frame metadata.",
+ "properties": [
+ { "name": "offsetTop", "type": "number", "hidden": true, "description": "Top offset in DIP." },
+ { "name": "pageScaleFactor", "type": "number", "hidden": true, "description": "Page scale factor." },
+ { "name": "deviceWidth", "type": "number", "hidden": true, "description": "Device screen width in DIP." },
+ { "name": "deviceHeight", "type": "number", "hidden": true, "description": "Device screen height in DIP." },
+ { "name": "scrollOffsetX", "type": "number", "hidden": true, "description": "Position of horizontal scroll in CSS pixels." },
+ { "name": "scrollOffsetY", "type": "number", "hidden": true, "description": "Position of vertical scroll in CSS pixels." },
+ { "name": "timestamp", "type": "number", "optional": true, "hidden": true, "description": "Frame swap timestamp." }
+ ],
+ "hidden": true
+ },
+ {
+ "id": "DialogType",
+ "description": "Javascript dialog type.",
+ "type": "string",
+ "enum": ["alert", "confirm", "prompt", "beforeunload"],
+ "hidden": true
+ },
+ {
+ "id": "AppManifestError",
+ "description": "Error while paring app manifest.",
+ "type": "object",
+ "properties": [
+ { "name": "message", "type": "string", "description": "Error message." },
+ { "name": "critical", "type": "integer", "description": "If criticial, this is a non-recoverable parse error." },
+ { "name": "line", "type": "integer", "description": "Error line." },
+ { "name": "column", "type": "integer", "description": "Error column." }
+ ],
+ "hidden": true
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables page domain notifications.",
+ "handlers": ["browser", "renderer"]
+ },
+ {
+ "name": "disable",
+ "description": "Disables page domain notifications.",
+ "handlers": ["browser", "renderer"]
+ },
+ {
+ "name": "addScriptToEvaluateOnLoad",
+ "parameters": [
+ { "name": "scriptSource", "type": "string" }
+ ],
+ "returns": [
+ { "name": "identifier", "$ref": "ScriptIdentifier", "description": "Identifier of the added script." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "removeScriptToEvaluateOnLoad",
+ "parameters": [
+ { "name": "identifier", "$ref": "ScriptIdentifier" }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "setAutoAttachToCreatedPages",
+ "parameters": [
+ { "name": "autoAttach", "type": "boolean", "description": "If true, browser will open a new inspector window for every page created from this one." }
+ ],
+ "description": "Controls whether browser will open a new inspector window for connected pages.",
+ "hidden": true
+ },
+ {
+ "name": "reload",
+ "parameters": [
+ { "name": "ignoreCache", "type": "boolean", "optional": true, "description": "If true, browser cache is ignored (as if the user pressed Shift+refresh)." },
+ { "name": "scriptToEvaluateOnLoad", "type": "string", "optional": true, "description": "If set, the script will be injected into all frames of the inspected page after reload." }
+ ],
+ "description": "Reloads given page optionally ignoring the cache.",
+ "handlers": ["browser", "renderer"]
+ },
+ {
+ "name": "navigate",
+ "parameters": [
+ { "name": "url", "type": "string", "description": "URL to navigate the page to." }
+ ],
+ "returns": [
+ { "name": "frameId", "$ref": "FrameId", "hidden": true, "description": "Frame id that will be navigated." }
+ ],
+ "description": "Navigates current page to the given URL.",
+ "handlers": ["browser", "renderer"]
+ },
+ {
+ "name": "getNavigationHistory",
+ "returns": [
+ { "name": "currentIndex", "type": "integer", "description": "Index of the current navigation history entry." },
+ { "name": "entries", "type": "array", "items": { "$ref": "NavigationEntry" }, "description": "Array of navigation history entries." }
+ ],
+ "description": "Returns navigation history for the current page.",
+ "hidden": true,
+ "handlers": ["browser"]
+ },
+ {
+ "name": "navigateToHistoryEntry",
+ "parameters": [
+ { "name": "entryId", "type": "integer", "description": "Unique id of the entry to navigate to." }
+ ],
+ "description": "Navigates current page to the given history entry.",
+ "hidden": true,
+ "handlers": ["browser"]
+ },
+ {
+ "name": "getCookies",
+ "returns": [
+ { "name": "cookies", "type": "array", "items": { "$ref": "Network.Cookie" }, "description": "Array of cookie objects." }
+ ],
+ "description": "Returns all browser cookies. Depending on the backend support, will return detailed cookie information in the <code>cookies</code> field.",
+ "handlers": ["browser"],
+ "async": true,
+ "hidden": true,
+ "redirect": "Network"
+ },
+ {
+ "name": "deleteCookie",
+ "parameters": [
+ { "name": "cookieName", "type": "string", "description": "Name of the cookie to remove." },
+ { "name": "url", "type": "string", "description": "URL to match cooke domain and path." }
+ ],
+ "description": "Deletes browser cookie with given name, domain and path.",
+ "handlers": ["browser"],
+ "async": true,
+ "hidden": true,
+ "redirect": "Network"
+ },
+ {
+ "name": "getResourceTree",
+ "description": "Returns present frame / resource tree structure.",
+ "returns": [
+ { "name": "frameTree", "$ref": "FrameResourceTree", "description": "Present frame / resource tree structure." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "getResourceContent",
+ "async": true,
+ "description": "Returns content of the given resource.",
+ "parameters": [
+ { "name": "frameId", "$ref": "FrameId", "description": "Frame id to get resource for." },
+ { "name": "url", "type": "string", "description": "URL of the resource to get content for." }
+ ],
+ "returns": [
+ { "name": "content", "type": "string", "description": "Resource content." },
+ { "name": "base64Encoded", "type": "boolean", "description": "True, if content was served as base64." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "searchInResource",
+ "async": true,
+ "description": "Searches for given string in resource content.",
+ "parameters": [
+ { "name": "frameId", "$ref": "FrameId", "description": "Frame id for resource to search in." },
+ { "name": "url", "type": "string", "description": "URL of the resource to search in." },
+ { "name": "query", "type": "string", "description": "String to search for." },
+ { "name": "caseSensitive", "type": "boolean", "optional": true, "description": "If true, search is case sensitive." },
+ { "name": "isRegex", "type": "boolean", "optional": true, "description": "If true, treats string parameter as regex." }
+ ],
+ "returns": [
+ { "name": "result", "type": "array", "items": { "$ref": "Debugger.SearchMatch" }, "description": "List of search matches." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "setDocumentContent",
+ "description": "Sets given markup as the document's HTML.",
+ "parameters": [
+ { "name": "frameId", "$ref": "FrameId", "description": "Frame id to set HTML for." },
+ { "name": "html", "type": "string", "description": "HTML content to set." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "setDeviceMetricsOverride",
+ "description": "Overrides the values of device screen dimensions (window.screen.width, window.screen.height, window.innerWidth, window.innerHeight, and \"device-width\"/\"device-height\"-related CSS media query results).",
+ "parameters": [
+ { "name": "width", "type": "integer", "description": "Overriding width value in pixels (minimum 0, maximum 10000000). 0 disables the override." },
+ { "name": "height", "type": "integer", "description": "Overriding height value in pixels (minimum 0, maximum 10000000). 0 disables the override." },
+ { "name": "deviceScaleFactor", "type": "number", "description": "Overriding device scale factor value. 0 disables the override." },
+ { "name": "mobile", "type": "boolean", "description": "Whether to emulate mobile device. This includes viewport meta tag, overlay scrollbars, text autosizing and more." },
+ { "name": "fitWindow", "type": "boolean", "description": "Whether a view that exceeds the available browser window area should be scaled down to fit." },
+ { "name": "scale", "type": "number", "optional": true, "description": "Scale to apply to resulting view image. Ignored in |fitWindow| mode." },
+ { "name": "offsetX", "type": "number", "optional": true, "description": "X offset to shift resulting view image by. Ignored in |fitWindow| mode." },
+ { "name": "offsetY", "type": "number", "optional": true, "description": "Y offset to shift resulting view image by. Ignored in |fitWindow| mode." },
+ { "name": "screenWidth", "type": "integer", "optional": true, "description": "Overriding screen width value in pixels (minimum 0, maximum 10000000). Only used for |mobile==true|." },
+ { "name": "screenHeight", "type": "integer", "optional": true, "description": "Overriding screen height value in pixels (minimum 0, maximum 10000000). Only used for |mobile==true|." },
+ { "name": "positionX", "type": "integer", "optional": true, "description": "Overriding view X position on screen in pixels (minimum 0, maximum 10000000). Only used for |mobile==true|." },
+ { "name": "positionY", "type": "integer", "optional": true, "description": "Overriding view Y position on screen in pixels (minimum 0, maximum 10000000). Only used for |mobile==true|." },
+ { "name": "screenOrientation", "$ref": "Emulation.ScreenOrientation", "optional": true, "description": "Screen orientation override." }
+ ],
+ "handlers": ["browser"],
+ "redirect": "Emulation",
+ "hidden": true
+ },
+ {
+ "name": "clearDeviceMetricsOverride",
+ "description": "Clears the overriden device metrics.",
+ "handlers": ["browser"],
+ "redirect": "Emulation",
+ "hidden": true
+ },
+ {
+ "name": "setGeolocationOverride",
+ "description": "Overrides the Geolocation Position or Error. Omitting any of the parameters emulates position unavailable.",
+ "parameters": [
+ { "name": "latitude", "type": "number", "optional": true, "description": "Mock latitude"},
+ { "name": "longitude", "type": "number", "optional": true, "description": "Mock longitude"},
+ { "name": "accuracy", "type": "number", "optional": true, "description": "Mock accuracy"}
+ ],
+ "redirect": "Emulation",
+ "handlers": ["browser"]
+ },
+ {
+ "name": "clearGeolocationOverride",
+ "description": "Clears the overriden Geolocation Position and Error.",
+ "redirect": "Emulation",
+ "handlers": ["browser"]
+ },
+ {
+ "name": "setDeviceOrientationOverride",
+ "description": "Overrides the Device Orientation.",
+ "parameters": [
+ { "name": "alpha", "type": "number", "description": "Mock alpha"},
+ { "name": "beta", "type": "number", "description": "Mock beta"},
+ { "name": "gamma", "type": "number", "description": "Mock gamma"}
+ ],
+ "redirect": "DeviceOrientation",
+ "hidden": true
+ },
+ {
+ "name": "clearDeviceOrientationOverride",
+ "description": "Clears the overridden Device Orientation.",
+ "redirect": "DeviceOrientation",
+ "hidden": true
+ },
+ {
+ "name": "setTouchEmulationEnabled",
+ "parameters": [
+ { "name": "enabled", "type": "boolean", "description": "Whether the touch event emulation should be enabled." },
+ { "name": "configuration", "type": "string", "enum": ["mobile", "desktop"], "optional": true, "description": "Touch/gesture events configuration. Default: current platform." }
+ ],
+ "description": "Toggles mouse event-based touch event emulation.",
+ "hidden": true,
+ "redirect": "Emulation",
+ "handlers": ["browser", "renderer"]
+ },
+ {
+ "name": "captureScreenshot",
+ "async": true,
+ "description": "Capture page screenshot.",
+ "returns": [
+ { "name": "data", "type": "string", "description": "Base64-encoded image data (PNG)." }
+ ],
+ "hidden": true,
+ "handlers": ["browser"]
+ },
+ {
+ "name": "startScreencast",
+ "description": "Starts sending each frame using the <code>screencastFrame</code> event.",
+ "parameters": [
+ { "name": "format", "type": "string", "optional": true, "enum": ["jpeg", "png"], "description": "Image compression format." },
+ { "name": "quality", "type": "integer", "optional": true, "description": "Compression quality from range [0..100]." },
+ { "name": "maxWidth", "type": "integer", "optional": true, "description": "Maximum screenshot width." },
+ { "name": "maxHeight", "type": "integer", "optional": true, "description": "Maximum screenshot height." },
+ { "name": "everyNthFrame", "type": "integer", "optional": true, "description": "Send every n-th frame." }
+ ],
+ "hidden": true,
+ "handlers": ["browser", "renderer"]
+ },
+ {
+ "name": "stopScreencast",
+ "description": "Stops sending each frame in the <code>screencastFrame</code>.",
+ "hidden": true,
+ "handlers": ["browser", "renderer"]
+ },
+ {
+ "name": "screencastFrameAck",
+ "description": "Acknowledges that a screencast frame has been received by the frontend.",
+ "parameters": [
+ { "name": "sessionId", "type": "integer", "description": "Frame number." }
+ ],
+ "hidden": true,
+ "handlers": ["browser"]
+ },
+ {
+ "name": "handleJavaScriptDialog",
+ "description": "Accepts or dismisses a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload).",
+ "parameters": [
+ { "name": "accept", "type": "boolean", "description": "Whether to accept or dismiss the dialog." },
+ { "name": "promptText", "type": "string", "optional": true, "description": "The text to enter into the dialog prompt before accepting. Used only if this is a prompt dialog." }
+ ],
+ "hidden": true,
+ "handlers": ["browser"]
+ },
+ {
+ "name": "setColorPickerEnabled",
+ "parameters": [
+ { "name": "enabled", "type": "boolean", "description": "Shows / hides color picker" }
+ ],
+ "description": "Shows / hides color picker",
+ "hidden": true,
+ "handlers": ["browser"]
+ },
+ {
+ "name": "setOverlayMessage",
+ "parameters": [
+ { "name": "message", "type": "string", "optional": true, "description": "Overlay message to display when paused in debugger." }
+ ],
+ "hidden": true,
+ "description": "Sets overlay message."
+ },
+ {
+ "name": "getAppManifest",
+ "hidden": true,
+ "returns": [
+ { "name": "url", "type": "string", "description": "Manifest location." },
+ { "name": "errors", "type": "array", "items": { "$ref": "AppManifestError" } },
+ { "name": "data", "type": "string", "optional": true, "description": "Manifest content." }
+ ],
+ "handlers": ["none"]
+ },
+ {
+ "name": "requestAppBanner",
+ "hidden": true,
+ "handlers": ["browser"]
+ },
+ {
+ "name": "setBlockedEventsWarningThreshold",
+ "hidden": true,
+ "parameters": [
+ { "name": "threshold", "type": "number", "description": "If set to a positive number, specifies threshold in seconds for input event latency that will cause a console warning about blocked event to be issued. If zero or less, the warning is disabled." }
+ ]
+ }
+ ],
+ "events": [
+ {
+ "name": "domContentEventFired",
+ "parameters": [
+ { "name": "timestamp", "type": "number" }
+ ]
+ },
+ {
+ "name": "loadEventFired",
+ "parameters": [
+ { "name": "timestamp", "type": "number" }
+ ]
+ },
+ {
+ "name": "frameAttached",
+ "description": "Fired when frame has been attached to its parent.",
+ "parameters": [
+ { "name": "frameId", "$ref": "FrameId", "description": "Id of the frame that has been attached." },
+ { "name": "parentFrameId", "$ref": "FrameId", "description": "Parent frame identifier." }
+ ]
+ },
+ {
+ "name": "frameNavigated",
+ "description": "Fired once navigation of the frame has completed. Frame is now associated with the new loader.",
+ "parameters": [
+ { "name": "frame", "$ref": "Frame", "description": "Frame object." }
+ ]
+ },
+ {
+ "name": "frameDetached",
+ "description": "Fired when frame has been detached from its parent.",
+ "parameters": [
+ { "name": "frameId", "$ref": "FrameId", "description": "Id of the frame that has been detached." }
+ ]
+ },
+ {
+ "name": "frameStartedLoading",
+ "description": "Fired when frame has started loading.",
+ "parameters": [
+ { "name": "frameId", "$ref": "FrameId", "description": "Id of the frame that has started loading." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "frameStoppedLoading",
+ "description": "Fired when frame has stopped loading.",
+ "parameters": [
+ { "name": "frameId", "$ref": "FrameId", "description": "Id of the frame that has stopped loading." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "frameScheduledNavigation",
+ "description": "Fired when frame schedules a potential navigation.",
+ "parameters": [
+ { "name": "frameId", "$ref": "FrameId", "description": "Id of the frame that has scheduled a navigation." },
+ { "name": "delay", "type": "number", "description": "Delay (in seconds) until the navigation is scheduled to begin. The navigation is not guaranteed to start." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "frameClearedScheduledNavigation",
+ "description": "Fired when frame no longer has a scheduled navigation.",
+ "parameters": [
+ { "name": "frameId", "$ref": "FrameId", "description": "Id of the frame that has cleared its scheduled navigation." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "frameResized",
+ "hidden": true
+ },
+ {
+ "name": "javascriptDialogOpening",
+ "description": "Fired when a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload) is about to open.",
+ "parameters": [
+ { "name": "message", "type": "string", "description": "Message that will be displayed by the dialog." },
+ { "name": "type", "$ref": "DialogType", "description": "Dialog type." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "javascriptDialogClosed",
+ "description": "Fired when a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload) has been closed.",
+ "parameters": [
+ { "name": "result", "type": "boolean", "description": "Whether dialog was confirmed." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "screencastFrame",
+ "description": "Compressed image data requested by the <code>startScreencast</code>.",
+ "parameters": [
+ { "name": "data", "type": "string", "description": "Base64-encoded compressed image." },
+ { "name": "metadata", "$ref": "ScreencastFrameMetadata", "description": "Screencast frame metadata."},
+ { "name": "sessionId", "type": "integer", "description": "Frame number."}
+ ],
+ "hidden": true,
+ "handlers": ["browser"]
+ },
+ {
+ "name": "screencastVisibilityChanged",
+ "description": "Fired when the page with currently enabled screencast was shown or hidden </code>.",
+ "parameters": [
+ { "name": "visible", "type": "boolean", "description": "True if the page is visible." }
+ ],
+ "hidden": true,
+ "handlers": ["browser"]
+ },
+ {
+ "name": "colorPicked",
+ "description": "Fired when a color has been picked.",
+ "parameters": [
+ { "name": "color", "$ref": "DOM.RGBA", "description": "RGBA of the picked color." }
+ ],
+ "hidden": true,
+ "handlers": ["browser"]
+ },
+ {
+ "name": "interstitialShown",
+ "description": "Fired when interstitial page was shown",
+ "hidden": true,
+ "handlers": ["browser"]
+ },
+ {
+ "name": "interstitialHidden",
+ "description": "Fired when interstitial page was hidden",
+ "hidden": true,
+ "handlers": ["browser"]
+ }
+ ]
+ },
+ {
+ "domain": "Rendering",
+ "description": "This domain allows to control rendering of the page.",
+ "hidden": true,
+ "commands": [
+ {
+ "name": "setShowPaintRects",
+ "description": "Requests that backend shows paint rectangles",
+ "parameters": [
+ { "name": "result", "type": "boolean", "description": "True for showing paint rectangles" }
+ ]
+ },
+ {
+ "name": "setShowDebugBorders",
+ "description": "Requests that backend shows debug borders on layers",
+ "parameters": [
+ { "name": "show", "type": "boolean", "description": "True for showing debug borders" }
+ ]
+ },
+ {
+ "name": "setShowFPSCounter",
+ "description": "Requests that backend shows the FPS counter",
+ "parameters": [
+ { "name": "show", "type": "boolean", "description": "True for showing the FPS counter" }
+ ]
+ },
+ {
+ "name": "setShowScrollBottleneckRects",
+ "description": "Requests that backend shows scroll bottleneck rects",
+ "parameters": [
+ { "name": "show", "type": "boolean", "description": "True for showing scroll bottleneck rects" }
+ ]
+ },
+ {
+ "name": "setShowViewportSizeOnResize",
+ "description": "Paints viewport size upon main frame resize.",
+ "parameters": [
+ { "name": "show", "type": "boolean", "description": "Whether to paint size or not." }
+ ]
+ }
+ ]
+ },
+ {
+ "domain": "Emulation",
+ "description": "This domain emulates different environments for the page.",
+ "hidden": true,
+ "types": [
+ {
+ "id": "ScreenOrientation",
+ "type": "object",
+ "description": "Screen orientation.",
+ "properties": [
+ { "name": "type", "type": "string", "enum": ["portraitPrimary", "portraitSecondary", "landscapePrimary", "landscapeSecondary"], "description": "Orientation type." },
+ { "name": "angle", "type": "integer", "description": "Orientation angle." }
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "setDeviceMetricsOverride",
+ "description": "Overrides the values of device screen dimensions (window.screen.width, window.screen.height, window.innerWidth, window.innerHeight, and \"device-width\"/\"device-height\"-related CSS media query results).",
+ "parameters": [
+ { "name": "width", "type": "integer", "description": "Overriding width value in pixels (minimum 0, maximum 10000000). 0 disables the override." },
+ { "name": "height", "type": "integer", "description": "Overriding height value in pixels (minimum 0, maximum 10000000). 0 disables the override." },
+ { "name": "deviceScaleFactor", "type": "number", "description": "Overriding device scale factor value. 0 disables the override." },
+ { "name": "mobile", "type": "boolean", "description": "Whether to emulate mobile device. This includes viewport meta tag, overlay scrollbars, text autosizing and more." },
+ { "name": "fitWindow", "type": "boolean", "description": "Whether a view that exceeds the available browser window area should be scaled down to fit." },
+ { "name": "scale", "type": "number", "optional": true, "description": "Scale to apply to resulting view image. Ignored in |fitWindow| mode." },
+ { "name": "offsetX", "type": "number", "optional": true, "description": "X offset to shift resulting view image by. Ignored in |fitWindow| mode." },
+ { "name": "offsetY", "type": "number", "optional": true, "description": "Y offset to shift resulting view image by. Ignored in |fitWindow| mode." },
+ { "name": "screenWidth", "type": "integer", "optional": true, "description": "Overriding screen width value in pixels (minimum 0, maximum 10000000). Only used for |mobile==true|." },
+ { "name": "screenHeight", "type": "integer", "optional": true, "description": "Overriding screen height value in pixels (minimum 0, maximum 10000000). Only used for |mobile==true|." },
+ { "name": "positionX", "type": "integer", "optional": true, "description": "Overriding view X position on screen in pixels (minimum 0, maximum 10000000). Only used for |mobile==true|." },
+ { "name": "positionY", "type": "integer", "optional": true, "description": "Overriding view Y position on screen in pixels (minimum 0, maximum 10000000). Only used for |mobile==true|." },
+ { "name": "screenOrientation", "$ref": "ScreenOrientation", "optional": true, "description": "Screen orientation override." }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "clearDeviceMetricsOverride",
+ "description": "Clears the overriden device metrics.",
+ "handlers": ["browser"]
+ },
+ {
+ "name": "resetPageScaleFactor",
+ "description": "Requests that page scale factor is reset to initial values."
+ },
+ {
+ "name": "setPageScaleFactor",
+ "description": "Sets a specified page scale factor.",
+ "parameters": [
+ { "name": "pageScaleFactor", "type": "number", "description": "Page scale factor." }
+ ]
+ },
+ {
+ "name": "setScriptExecutionDisabled",
+ "description": "Switches script execution in the page.",
+ "parameters": [
+ { "name": "value", "type": "boolean", "description": "Whether script execution should be disabled in the page." }
+ ]
+ },
+ {
+ "name": "setGeolocationOverride",
+ "description": "Overrides the Geolocation Position or Error. Omitting any of the parameters emulates position unavailable.",
+ "parameters": [
+ { "name": "latitude", "type": "number", "optional": true, "description": "Mock latitude"},
+ { "name": "longitude", "type": "number", "optional": true, "description": "Mock longitude"},
+ { "name": "accuracy", "type": "number", "optional": true, "description": "Mock accuracy"}
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "clearGeolocationOverride",
+ "description": "Clears the overriden Geolocation Position and Error.",
+ "handlers": ["browser"]
+ },
+ {
+ "name": "setTouchEmulationEnabled",
+ "parameters": [
+ { "name": "enabled", "type": "boolean", "description": "Whether the touch event emulation should be enabled." },
+ { "name": "configuration", "type": "string", "enum": ["mobile", "desktop"], "optional": true, "description": "Touch/gesture events configuration. Default: current platform." }
+ ],
+ "description": "Toggles mouse event-based touch event emulation.",
+ "handlers": ["browser", "renderer"]
+ },
+ {
+ "name": "setEmulatedMedia",
+ "parameters": [
+ { "name": "media", "type": "string", "description": "Media type to emulate. Empty string disables the override." }
+ ],
+ "description": "Emulates the given media for CSS media queries."
+ },
+ {
+ "name": "setCPUThrottlingRate",
+ "parameters": [
+ { "name": "rate", "type": "number", "description": "Throttling rate as a slowdown factor (1 is no throttle, 2 is 2x slowdown, etc)." }
+ ],
+ "description": "Enables CPU throttling to emulate slow CPUs."
+ },
+ {
+ "name": "canEmulate",
+ "description": "Tells whether emulation is supported.",
+ "returns": [
+ { "name": "result", "type": "boolean", "description": "True if emulation is supported." }
+ ],
+ "handlers": ["browser"]
+ }
+ ]
+ },
+ {
+ "domain": "Runtime",
+ "description": "Runtime domain exposes JavaScript runtime by means of remote evaluation and mirror objects. Evaluation results are returned as mirror object that expose object type, string representation and unique identifier that can be used for further object reference. Original objects are maintained in memory unless they are either explicitly released or are released along with the other objects in their object group.",
+ "types": [
+ {
+ "id": "ScriptId",
+ "type": "string",
+ "description": "Unique script identifier."
+ },
+ {
+ "id": "RemoteObjectId",
+ "type": "string",
+ "description": "Unique object identifier."
+ },
+ {
+ "id": "RemoteObject",
+ "type": "object",
+ "description": "Mirror object referencing original JavaScript object.",
+ "properties": [
+ { "name": "type", "type": "string", "enum": ["object", "function", "undefined", "string", "number", "boolean", "symbol"], "description": "Object type." },
+ { "name": "subtype", "type": "string", "optional": true, "enum": ["array", "null", "node", "regexp", "date", "map", "set", "iterator", "generator", "error"], "description": "Object subtype hint. Specified for <code>object</code> type values only." },
+ { "name": "className", "type": "string", "optional": true, "description": "Object class (constructor) name. Specified for <code>object</code> type values only." },
+ { "name": "value", "type": "any", "optional": true, "description": "Remote object value in case of primitive values or JSON values (if it was requested), or description string if the value can not be JSON-stringified (like NaN, Infinity, -Infinity, -0)." },
+ { "name": "description", "type": "string", "optional": true, "description": "String representation of the object." },
+ { "name": "objectId", "$ref": "RemoteObjectId", "optional": true, "description": "Unique object identifier (for non-primitive values)." },
+ { "name": "preview", "$ref": "ObjectPreview", "optional": true, "description": "Preview containing abbreviated property values. Specified for <code>object</code> type values only.", "hidden": true },
+ { "name": "customPreview", "$ref": "CustomPreview", "optional": true, "hidden": true}
+ ]
+ },
+ {
+ "id": "CustomPreview",
+ "type": "object",
+ "hidden": true,
+ "properties": [
+ { "name": "header", "type": "string"},
+ { "name": "hasBody", "type": "boolean"},
+ { "name": "formatterObjectId", "$ref": "RemoteObjectId"},
+ { "name": "bindRemoteObjectFunctionId", "$ref": "RemoteObjectId" },
+ { "name": "configObjectId", "$ref": "RemoteObjectId", "optional": true }
+ ]
+ },
+ {
+ "id": "ObjectPreview",
+ "type": "object",
+ "hidden": true,
+ "description": "Object containing abbreviated remote object value.",
+ "properties": [
+ { "name": "type", "type": "string", "enum": ["object", "function", "undefined", "string", "number", "boolean", "symbol"], "description": "Object type." },
+ { "name": "subtype", "type": "string", "optional": true, "enum": ["array", "null", "node", "regexp", "date", "map", "set", "iterator", "generator", "error"], "description": "Object subtype hint. Specified for <code>object</code> type values only." },
+ { "name": "description", "type": "string", "optional": true, "description": "String representation of the object." },
+ { "name": "overflow", "type": "boolean", "description": "True iff some of the properties or entries of the original object did not fit." },
+ { "name": "properties", "type": "array", "items": { "$ref": "PropertyPreview" }, "description": "List of the properties." },
+ { "name": "entries", "type": "array", "items": { "$ref": "EntryPreview" }, "optional": true, "description": "List of the entries. Specified for <code>map</code> and <code>set</code> subtype values only." }
+ ]
+ },
+ {
+ "id": "PropertyPreview",
+ "type": "object",
+ "hidden": true,
+ "properties": [
+ { "name": "name", "type": "string", "description": "Property name." },
+ { "name": "type", "type": "string", "enum": ["object", "function", "undefined", "string", "number", "boolean", "symbol", "accessor"], "description": "Object type. Accessor means that the property itself is an accessor property." },
+ { "name": "value", "type": "string", "optional": true, "description": "User-friendly property value string." },
+ { "name": "valuePreview", "$ref": "ObjectPreview", "optional": true, "description": "Nested value preview." },
+ { "name": "subtype", "type": "string", "optional": true, "enum": ["array", "null", "node", "regexp", "date", "map", "set", "iterator", "generator", "error"], "description": "Object subtype hint. Specified for <code>object</code> type values only." }
+ ]
+ },
+ {
+ "id": "EntryPreview",
+ "type": "object",
+ "hidden": true,
+ "properties": [
+ { "name": "key", "$ref": "ObjectPreview", "optional": true, "description": "Preview of the key. Specified for map-like collection entries." },
+ { "name": "value", "$ref": "ObjectPreview", "description": "Preview of the value." }
+ ]
+ },
+ {
+ "id": "PropertyDescriptor",
+ "type": "object",
+ "description": "Object property descriptor.",
+ "properties": [
+ { "name": "name", "type": "string", "description": "Property name or symbol description." },
+ { "name": "value", "$ref": "RemoteObject", "optional": true, "description": "The value associated with the property." },
+ { "name": "writable", "type": "boolean", "optional": true, "description": "True if the value associated with the property may be changed (data descriptors only)." },
+ { "name": "get", "$ref": "RemoteObject", "optional": true, "description": "A function which serves as a getter for the property, or <code>undefined</code> if there is no getter (accessor descriptors only)." },
+ { "name": "set", "$ref": "RemoteObject", "optional": true, "description": "A function which serves as a setter for the property, or <code>undefined</code> if there is no setter (accessor descriptors only)." },
+ { "name": "configurable", "type": "boolean", "description": "True if the type of this property descriptor may be changed and if the property may be deleted from the corresponding object." },
+ { "name": "enumerable", "type": "boolean", "description": "True if this property shows up during enumeration of the properties on the corresponding object." },
+ { "name": "wasThrown", "type": "boolean", "optional": true, "description": "True if the result was thrown during the evaluation." },
+ { "name": "isOwn", "optional": true, "type": "boolean", "description": "True if the property is owned for the object.", "hidden": true },
+ { "name": "symbol", "$ref": "RemoteObject", "optional": true, "description": "Property symbol object, if the property is of the <code>symbol</code> type.", "hidden": true }
+ ]
+ },
+ {
+ "id": "InternalPropertyDescriptor",
+ "type": "object",
+ "description": "Object internal property descriptor. This property isn't normally visible in JavaScript code.",
+ "properties": [
+ { "name": "name", "type": "string", "description": "Conventional property name." },
+ { "name": "value", "$ref": "RemoteObject", "optional": true, "description": "The value associated with the property." }
+ ],
+ "hidden": true
+ },
+ {
+ "id": "CallArgument",
+ "type": "object",
+ "description": "Represents function call argument. Either remote object id <code>objectId</code> or primitive <code>value</code> or neither of (for undefined) them should be specified.",
+ "properties": [
+ { "name": "value", "type": "any", "optional": true, "description": "Primitive value, or description string if the value can not be JSON-stringified (like NaN, Infinity, -Infinity, -0)." },
+ { "name": "objectId", "$ref": "RemoteObjectId", "optional": true, "description": "Remote object handle." },
+ { "name": "type", "optional": true, "hidden": true, "type": "string", "enum": ["object", "function", "undefined", "string", "number", "boolean", "symbol"], "description": "Object type." }
+ ]
+ },
+ {
+ "id": "ExecutionContextId",
+ "type": "integer",
+ "description": "Id of an execution context."
+ },
+ {
+ "id": "ExecutionContextDescription",
+ "type": "object",
+ "description": "Description of an isolated world.",
+ "properties": [
+ { "name": "id", "$ref": "ExecutionContextId", "description": "Unique id of the execution context. It can be used to specify in which execution context script evaluation should be performed." },
+ { "name": "isDefault", "type": "boolean", "description": "Whether context is the default page context (as opposite to e.g. context of content script).", "hidden": true },
+ { "name": "origin", "type": "string", "description": "Execution context origin.", "hidden": true},
+ { "name": "name", "type": "string", "description": "Human readable name describing given context.", "hidden": true},
+ { "name": "frameId", "type": "string", "description": "Id of the owning frame. May be an empty string if the context is not associated with a frame." }
+ ]
+ },
+ {
+ "id": "ExceptionDetails",
+ "type": "object",
+ "description": "Detailed information on exception (or error) that was thrown during script compilation or execution.",
+ "properties": [
+ { "name": "text", "type": "string", "description": "Exception text." },
+ { "name": "url", "type": "string", "optional": true, "description": "URL of the message origin." },
+ { "name": "scriptId", "type": "string", "optional": true, "description": "Script ID of the message origin." },
+ { "name": "line", "type": "integer", "optional": true, "description": "Line number in the resource that generated this message." },
+ { "name": "column", "type": "integer", "optional": true, "description": "Column number in the resource that generated this message." },
+ { "name": "stack", "$ref": "StackTrace", "optional": true, "description": "JavaScript stack trace for assertions and error messages." }
+ ]
+ },
+ {
+ "id": "CallFrame",
+ "type": "object",
+ "description": "Stack entry for runtime errors and assertions.",
+ "properties": [
+ { "name": "functionName", "type": "string", "description": "JavaScript function name." },
+ { "name": "scriptId", "$ref": "ScriptId", "description": "JavaScript script id." },
+ { "name": "url", "type": "string", "description": "JavaScript script name or url." },
+ { "name": "lineNumber", "type": "integer", "description": "JavaScript script line number." },
+ { "name": "columnNumber", "type": "integer", "description": "JavaScript script column number." }
+ ]
+ },
+ {
+ "id": "StackTrace",
+ "type": "object",
+ "description": "Call frames for assertions or error messages.",
+ "properties": [
+ { "name": "description", "type": "string", "optional": true, "description": "String label of this stack trace. For async traces this may be a name of the function that initiated the async call." },
+ { "name": "callFrames", "type": "array", "items": { "$ref": "CallFrame" }, "description": "JavaScript function name." },
+ { "name": "parent", "$ref": "StackTrace", "optional": true, "hidden": true, "hidden": true, "description": "Asynchronous JavaScript stack trace that preceded this stack, if available." }
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "evaluate",
+ "parameters": [
+ { "name": "expression", "type": "string", "description": "Expression to evaluate." },
+ { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." },
+ { "name": "includeCommandLineAPI", "type": "boolean", "optional": true, "description": "Determines whether Command Line API should be available during the evaluation.", "hidden": true },
+ { "name": "doNotPauseOnExceptionsAndMuteConsole", "type": "boolean", "optional": true, "description": "Specifies whether evaluation should stop on exceptions and mute console. Overrides setPauseOnException state.", "hidden": true },
+ { "name": "contextId", "$ref": "ExecutionContextId", "optional": true, "description": "Specifies in which isolated context to perform evaluation. Each content script lives in an isolated context and this parameter may be used to specify one of those contexts. If the parameter is omitted or 0 the evaluation will be performed in the context of the inspected page." },
+ { "name": "returnByValue", "type": "boolean", "optional": true, "description": "Whether the result is expected to be a JSON object that should be sent by value." },
+ { "name": "generatePreview", "type": "boolean", "optional": true, "hidden": true, "description": "Whether preview should be generated for the result." },
+ { "name": "userGesture", "type": "boolean", "optional": true, "hidden": true, "description": "Whether execution should be treated as initiated by user in the UI." }
+ ],
+ "returns": [
+ { "name": "result", "$ref": "RemoteObject", "description": "Evaluation result." },
+ { "name": "wasThrown", "type": "boolean", "optional": true, "description": "True if the result was thrown during the evaluation." },
+ { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "hidden": true, "description": "Exception details."}
+ ],
+ "description": "Evaluates expression on global object."
+ },
+ {
+ "name": "callFunctionOn",
+ "parameters": [
+ { "name": "objectId", "$ref": "RemoteObjectId", "description": "Identifier of the object to call function on." },
+ { "name": "functionDeclaration", "type": "string", "description": "Declaration of the function to call." },
+ { "name": "arguments", "type": "array", "items": { "$ref": "CallArgument", "description": "Call argument." }, "optional": true, "description": "Call arguments. All call arguments must belong to the same JavaScript world as the target object." },
+ { "name": "doNotPauseOnExceptionsAndMuteConsole", "type": "boolean", "optional": true, "description": "Specifies whether function call should stop on exceptions and mute console. Overrides setPauseOnException state.", "hidden": true },
+ { "name": "returnByValue", "type": "boolean", "optional": true, "description": "Whether the result is expected to be a JSON object which should be sent by value." },
+ { "name": "generatePreview", "type": "boolean", "optional": true, "hidden": true, "description": "Whether preview should be generated for the result." },
+ { "name": "userGesture", "type": "boolean", "optional": true, "hidden": true, "description": "Whether execution should be treated as initiated by user in the UI." }
+ ],
+ "returns": [
+ { "name": "result", "$ref": "RemoteObject", "description": "Call result." },
+ { "name": "wasThrown", "type": "boolean", "optional": true, "description": "True if the result was thrown during the evaluation." }
+ ],
+ "description": "Calls function with given declaration on the given object. Object group of the result is inherited from the target object."
+ },
+ {
+ "name": "getProperties",
+ "parameters": [
+ { "name": "objectId", "$ref": "RemoteObjectId", "description": "Identifier of the object to return properties for." },
+ { "name": "ownProperties", "optional": true, "type": "boolean", "description": "If true, returns properties belonging only to the element itself, not to its prototype chain." },
+ { "name": "accessorPropertiesOnly", "optional": true, "type": "boolean", "description": "If true, returns accessor properties (with getter/setter) only; internal properties are not returned either.", "hidden": true },
+ { "name": "generatePreview", "type": "boolean", "optional": true, "hidden": true, "description": "Whether preview should be generated for the results." }
+ ],
+ "returns": [
+ { "name": "result", "type": "array", "items": { "$ref": "PropertyDescriptor" }, "description": "Object properties." },
+ { "name": "internalProperties", "optional": true, "type": "array", "items": { "$ref": "InternalPropertyDescriptor" }, "description": "Internal object properties (only of the element itself).", "hidden": true },
+ { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "hidden": true, "description": "Exception details."}
+ ],
+ "description": "Returns properties of a given object. Object group of the result is inherited from the target object."
+ },
+ {
+ "name": "releaseObject",
+ "parameters": [
+ { "name": "objectId", "$ref": "RemoteObjectId", "description": "Identifier of the object to release." }
+ ],
+ "description": "Releases remote object with given id."
+ },
+ {
+ "name": "releaseObjectGroup",
+ "parameters": [
+ { "name": "objectGroup", "type": "string", "description": "Symbolic object group name." }
+ ],
+ "description": "Releases all remote objects that belong to a given group."
+ },
+ {
+ "name": "run",
+ "hidden": true,
+ "description": "Tells inspected instance(worker or page) that it can run in case it was started paused."
+ },
+ {
+ "name": "enable",
+ "description": "Enables reporting of execution contexts creation by means of <code>executionContextCreated</code> event. When the reporting gets enabled the event will be sent immediately for each existing execution context."
+ },
+ {
+ "name": "disable",
+ "hidden": true,
+ "description": "Disables reporting of execution contexts creation."
+ },
+ {
+ "name": "setCustomObjectFormatterEnabled",
+ "parameters": [
+ {
+ "name": "enabled",
+ "type": "boolean"
+ }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "compileScript",
+ "hidden": true,
+ "parameters": [
+ { "name": "expression", "type": "string", "description": "Expression to compile." },
+ { "name": "sourceURL", "type": "string", "description": "Source url to be set for the script." },
+ { "name": "persistScript", "type": "boolean", "description": "Specifies whether the compiled script should be persisted." },
+ { "name": "executionContextId", "$ref": "ExecutionContextId", "description": "Specifies in which isolated context to perform script run. Each content script lives in an isolated context and this parameter is used to specify one of those contexts." }
+ ],
+ "returns": [
+ { "name": "scriptId", "$ref": "ScriptId", "optional": true, "description": "Id of the script." },
+ { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "description": "Exception details."}
+ ],
+ "description": "Compiles expression."
+ },
+ {
+ "name": "runScript",
+ "hidden": true,
+ "parameters": [
+ { "name": "scriptId", "$ref": "ScriptId", "description": "Id of the script to run." },
+ { "name": "executionContextId", "$ref": "ExecutionContextId", "description": "Specifies in which isolated context to perform script run. Each content script lives in an isolated context and this parameter is used to specify one of those contexts." },
+ { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." },
+ { "name": "doNotPauseOnExceptionsAndMuteConsole", "type": "boolean", "optional": true, "description": "Specifies whether script run should stop on exceptions and mute console. Overrides setPauseOnException state." },
+ { "name": "includeCommandLineAPI", "type": "boolean", "optional": true, "description": "Determines whether Command Line API should be available during the evaluation." }
+ ],
+ "returns": [
+ { "name": "result", "$ref": "RemoteObject", "description": "Run result." },
+ { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "description": "Exception details."}
+ ],
+ "description": "Runs script with given id in a given context."
+ }
+ ],
+ "events": [
+ {
+ "name": "executionContextCreated",
+ "parameters": [
+ { "name": "context", "$ref": "ExecutionContextDescription", "description": "A newly created execution contex." }
+ ],
+ "description": "Issued when new execution context is created."
+ },
+ {
+ "name": "executionContextDestroyed",
+ "parameters": [
+ { "name": "executionContextId", "$ref": "ExecutionContextId", "description": "Id of the destroyed context" }
+ ],
+ "description": "Issued when execution context is destroyed."
+ },
+ {
+ "name": "executionContextsCleared",
+ "description": "Issued when all executionContexts were cleared in browser"
+ },
+ {
+ "name": "inspectRequested",
+ "parameters": [
+ { "name": "object", "$ref": "RemoteObject" },
+ { "name": "hints", "type": "object" }
+ ],
+ "hidden": true
+ }
+ ]
+ },
+ {
+ "domain": "Console",
+ "description": "Console domain defines methods and events for interaction with the JavaScript console. Console collects messages created by means of the <a href='http://getfirebug.com/wiki/index.php/Console_API'>JavaScript Console API</a>. One needs to enable this domain using <code>enable</code> command in order to start receiving the console messages. Browser collects messages issued while console domain is not enabled as well and reports them using <code>messageAdded</code> notification upon enabling.",
+ "types": [
+ {
+ "id": "Timestamp",
+ "type": "number",
+ "description": "Number of seconds since epoch.",
+ "hidden": true
+ },
+ {
+ "id": "ConsoleMessage",
+ "type": "object",
+ "description": "Console message.",
+ "properties": [
+ { "name": "source", "type": "string", "enum": ["xml", "javascript", "network", "console-api", "storage", "appcache", "rendering", "security", "other", "deprecation"], "description": "Message source." },
+ { "name": "level", "type": "string", "enum": ["log", "warning", "error", "debug", "info", "revokedError"], "description": "Message severity." },
+ { "name": "text", "type": "string", "description": "Message text." },
+ { "name": "type", "type": "string", "optional": true, "enum": ["log", "dir", "dirxml", "table", "trace", "clear", "startGroup", "startGroupCollapsed", "endGroup", "assert", "profile", "profileEnd"], "description": "Console message type." },
+ { "name": "scriptId", "type": "string", "optional": true, "description": "Script ID of the message origin." },
+ { "name": "url", "type": "string", "optional": true, "description": "URL of the message origin." },
+ { "name": "line", "type": "integer", "optional": true, "description": "Line number in the resource that generated this message." },
+ { "name": "column", "type": "integer", "optional": true, "description": "Column number in the resource that generated this message." },
+ { "name": "repeatCount", "type": "integer", "optional": true, "description": "Repeat count for repeated messages." },
+ { "name": "parameters", "type": "array", "items": { "$ref": "Runtime.RemoteObject" }, "optional": true, "description": "Message parameters in case of the formatted message." },
+ { "name": "stack", "$ref": "Runtime.StackTrace", "optional": true, "description": "JavaScript stack trace for assertions and error messages." },
+ { "name": "networkRequestId", "$ref": "Network.RequestId", "optional": true, "description": "Identifier of the network request associated with this message." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp, when this message was fired.", "hidden": true },
+ { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "optional": true, "description": "Identifier of the context where this message was created", "hidden": true },
+ { "name": "messageId", "type": "integer", "hidden": true, "optional": true, "description": "Message id." },
+ { "name": "relatedMessageId", "type": "integer", "hidden": true, "optional": true, "description": "Related message id." }
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables console domain, sends the messages collected so far to the client by means of the <code>messageAdded</code> notification."
+ },
+ {
+ "name": "disable",
+ "description": "Disables console domain, prevents further console messages from being reported to the client."
+ },
+ {
+ "name": "clearMessages",
+ "description": "Clears console messages collected in the browser."
+ }
+ ],
+ "events": [
+ {
+ "name": "messageAdded",
+ "parameters": [
+ { "name": "message", "$ref": "ConsoleMessage", "description": "Console message that has been added." }
+ ],
+ "description": "Issued when new console message is added."
+ },
+ {
+ "name": "messageRepeatCountUpdated",
+ "parameters": [
+ { "name": "count", "type": "integer", "description": "New repeat count value." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp of most recent message in batch.", "hidden": true }
+ ],
+ "description": "Is not issued. Will be gone in the future versions of the protocol.",
+ "deprecated": true
+ },
+ {
+ "name": "messagesCleared",
+ "description": "Issued when console is cleared. This happens either upon <code>clearMessages</code> command or after page navigation."
+ }
+ ]
+ },
+ {
+ "domain": "Security",
+ "description": "Security",
+ "hidden": true,
+ "types": [
+ {
+ "id": "SecurityState",
+ "type": "string",
+ "enum": ["unknown", "neutral", "insecure", "warning", "secure", "info"],
+ "description": "The security level of a page or resource."
+ },
+ {
+ "id": "SecurityStateExplanation",
+ "type": "object",
+ "properties": [
+ { "name": "securityState", "$ref": "SecurityState", "description": "Security state representing the severity of the factor being explained." },
+ { "name": "summary", "type": "string", "description": "Short phrase describing the type of factor." },
+ { "name": "description", "type": "string", "description": "Full text explanation of the factor." },
+ { "name": "certificateId", "$ref": "Network.CertificateId", "optional": true, "description": "Associated certificate id." }
+ ],
+ "description": "An explanation of an factor contributing to the security state."
+ },
+ {
+ "id": "MixedContentStatus",
+ "type": "object",
+ "properties": [
+ { "name": "ranInsecureContent", "type": "boolean", "description": "True if the page ran insecure content such as scripts." },
+ { "name": "displayedInsecureContent", "type": "boolean", "description": "True if the page displayed insecure content such as images." },
+ { "name": "ranInsecureContentStyle", "$ref": "SecurityState", "description": "Security state representing a page that ran insecure content." },
+ { "name": "displayedInsecureContentStyle", "$ref": "SecurityState", "description": "Security state representing a page that displayed insecure content." }
+ ],
+ "description": "Information about mixed content on the page."
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables tracking security state changes.",
+ "handlers": ["browser"]
+ },
+ {
+ "name": "disable",
+ "description": "Disables tracking security state changes.",
+ "handlers": ["browser"]
+ }
+ ],
+ "events": [
+ {
+ "name": "securityStateChanged",
+ "description": "The security state of the page changed.",
+ "parameters": [
+ { "name": "securityState", "$ref": "SecurityState", "description": "Security state." },
+ { "name": "explanations", "type": "array", "items": { "$ref": "SecurityStateExplanation" }, "description": "List of explanations for the security state. If the overall security state is `insecure` or `warning`, at least one corresponding explanation should be included.", "optional": true },
+ { "name": "mixedContentStatus", "$ref": "MixedContentStatus", "description": "Information about mixed content on the page.", "optional": true },
+ { "name": "schemeIsCryptographic", "type": "boolean", "description": "True if the page was loaded over cryptographic transport such as HTTPS.", "optional": true }
+ ],
+ "handlers": ["browser"]
+ }
+ ]
+ },
+ {
+ "domain": "Network",
+ "description": "Network domain allows tracking network activities of the page. It exposes information about http, file, data and other requests and responses, their headers, bodies, timing, etc.",
+ "types": [
+ {
+ "id": "LoaderId",
+ "type": "string",
+ "description": "Unique loader identifier."
+ },
+ {
+ "id": "RequestId",
+ "type": "string",
+ "description": "Unique request identifier."
+ },
+ {
+ "id": "Timestamp",
+ "type": "number",
+ "description": "Number of seconds since epoch."
+ },
+ {
+ "id": "Headers",
+ "type": "object",
+ "description": "Request / response headers as keys / values of JSON object."
+ },
+ {
+ "id": "ResourceTiming",
+ "type": "object",
+ "description": "Timing information for the request.",
+ "properties": [
+ { "name": "requestTime", "type": "number", "description": "Timing's requestTime is a baseline in seconds, while the other numbers are ticks in milliseconds relatively to this requestTime." },
+ { "name": "proxyStart", "type": "number", "description": "Started resolving proxy." },
+ { "name": "proxyEnd", "type": "number", "description": "Finished resolving proxy." },
+ { "name": "dnsStart", "type": "number", "description": "Started DNS address resolve." },
+ { "name": "dnsEnd", "type": "number", "description": "Finished DNS address resolve." },
+ { "name": "connectStart", "type": "number", "description": "Started connecting to the remote host." },
+ { "name": "connectEnd", "type": "number", "description": "Connected to the remote host." },
+ { "name": "sslStart", "type": "number", "description": "Started SSL handshake." },
+ { "name": "sslEnd", "type": "number", "description": "Finished SSL handshake." },
+ { "name": "workerStart", "type": "number", "description": "Started running ServiceWorker.", "hidden": true },
+ { "name": "workerReady", "type": "number", "description": "Finished Starting ServiceWorker.", "hidden": true },
+ { "name": "sendStart", "type": "number", "description": "Started sending request." },
+ { "name": "sendEnd", "type": "number", "description": "Finished sending request." },
+ { "name": "pushStart", "type": "number", "description": "Time the server started pushing request.", "hidden": true },
+ { "name": "pushEnd", "type": "number", "description": "Time the server finished pushing request.", "hidden": true },
+ { "name": "receiveHeadersEnd", "type": "number", "description": "Finished receiving response headers." }
+ ]
+ },
+ {
+ "id": "ResourcePriority",
+ "type": "string",
+ "enum": ["VeryLow", "Low", "Medium", "High", "VeryHigh"],
+ "description": "Loading priority of a resource request."
+ },
+ {
+ "id": "Request",
+ "type": "object",
+ "description": "HTTP request data.",
+ "properties": [
+ { "name": "url", "type": "string", "description": "Request URL." },
+ { "name": "method", "type": "string", "description": "HTTP request method." },
+ { "name": "headers", "$ref": "Headers", "description": "HTTP request headers." },
+ { "name": "postData", "type": "string", "optional": true, "description": "HTTP POST request data." },
+ { "name": "mixedContentType", "optional": true, "type": "string", "enum": ["blockable", "optionally-blockable", "none"], "description": "The mixed content status of the request, as defined in http://www.w3.org/TR/mixed-content/" },
+ { "name": "initialPriority", "$ref": "ResourcePriority", "description": "Priority of the resource request at the time request is sent."}
+ ]
+ },
+ {
+ "id": "CertificateId",
+ "type": "integer",
+ "description": "An internal certificate ID value."
+ },
+ {
+ "id": "CertificateSubject",
+ "type": "object",
+ "description": "Subject of a certificate.",
+ "properties": [
+ { "name": "name", "type": "string", "description": "Certificate subject name." },
+ { "name": "sanDnsNames", "type": "array", "items": { "type": "string" }, "description": "Subject Alternative Name (SAN) DNS names." },
+ { "name": "sanIpAddresses", "type": "array", "items": { "type": "string" }, "description": "Subject Alternative Name (SAN) IP addresses." }
+ ]
+ },
+ {
+ "id": "CertificateDetails",
+ "type": "object",
+ "description": "Details about a request's certificate.",
+ "properties": [
+ { "name": "subject", "$ref": "CertificateSubject", "description": "Certificate subject." },
+ { "name": "issuer", "type": "string", "description": "Name of the issuing CA." },
+ { "name": "validFrom", "$ref": "Timestamp", "description": "Certificate valid from date." },
+ { "name": "validTo", "$ref": "Timestamp", "description": "Certificate valid to (expiration) date" }
+ ]
+ },
+ {
+ "id": "CertificateValidationDetails",
+ "type": "object",
+ "description": "Details about the validation status of a request's certificate.",
+ "properties": [
+ { "name": "numUnknownScts", "type": "integer", "description": "The number of SCTs from unknown logs." },
+ { "name": "numInvalidScts", "type": "integer", "description": "The number of invalid SCTs." },
+ { "name": "numValidScts", "type": "integer", "description": "The number of valid SCTs." }
+ ]
+ },
+ {
+ "id": "SecurityDetails",
+ "type": "object",
+ "description": "Security details about a request.",
+ "properties": [
+ { "name": "protocol", "type": "string", "description": "Protocol name (e.g. \"TLS 1.2\" or \"QUIC\")." },
+ { "name": "keyExchange", "type": "string", "description": "Key Exchange used by the connection." },
+ { "name": "cipher", "type": "string", "description": "Cipher name." },
+ { "name": "mac", "type": "string", "optional": true, "description": "TLS MAC. Note that AEAD ciphers do not have separate MACs." },
+ { "name": "certificateId", "$ref": "CertificateId", "description": "Certificate ID value." },
+ { "name": "certificateValidationDetails", "$ref": "CertificateValidationDetails", "optional": true, "description": "Validation details for the request's certficate." }
+ ]
+ },
+ {
+ "id": "BlockedReason",
+ "type": "string",
+ "description": "The reason why request was blocked.",
+ "enum": ["csp", "mixed-content", "origin", "inspector", "other"],
+ "hidden": true
+ },
+ {
+ "id": "Response",
+ "type": "object",
+ "description": "HTTP response data.",
+ "properties": [
+ { "name": "url", "type": "string", "description": "Response URL. This URL can be different from CachedResource.url in case of redirect." },
+ { "name": "status", "type": "number", "description": "HTTP response status code." },
+ { "name": "statusText", "type": "string", "description": "HTTP response status text." },
+ { "name": "headers", "$ref": "Headers", "description": "HTTP response headers." },
+ { "name": "headersText", "type": "string", "optional": true, "description": "HTTP response headers text." },
+ { "name": "mimeType", "type": "string", "description": "Resource mimeType as determined by the browser." },
+ { "name": "requestHeaders", "$ref": "Headers", "optional": true, "description": "Refined HTTP request headers that were actually transmitted over the network." },
+ { "name": "requestHeadersText", "type": "string", "optional": true, "description": "HTTP request headers text." },
+ { "name": "connectionReused", "type": "boolean", "description": "Specifies whether physical connection was actually reused for this request." },
+ { "name": "connectionId", "type": "number", "description": "Physical connection id that was actually used for this request." },
+ { "name": "remoteIPAddress", "type": "string", "optional": true, "hidden": true, "description": "Remote IP address." },
+ { "name": "remotePort", "type": "integer", "optional": true, "hidden": true, "description": "Remote port."},
+ { "name": "fromDiskCache", "type": "boolean", "optional": true, "description": "Specifies that the request was served from the disk cache." },
+ { "name": "fromServiceWorker", "type": "boolean", "optional": true, "description": "Specifies that the request was served from the ServiceWorker." },
+ { "name": "encodedDataLength", "type": "number", "optional": false, "description": "Total number of bytes received for this request so far." },
+ { "name": "timing", "$ref": "ResourceTiming", "optional": true, "description": "Timing information for the given request." },
+ { "name": "protocol", "type": "string", "optional": true, "description": "Protocol used to fetch this request." },
+ { "name": "securityState", "$ref": "Security.SecurityState", "description": "Security state of the request resource." },
+ { "name": "securityDetails", "$ref": "SecurityDetails", "optional": true, "description": "Security details for the request." }
+ ]
+ },
+ {
+ "id": "WebSocketRequest",
+ "type": "object",
+ "description": "WebSocket request data.",
+ "hidden": true,
+ "properties": [
+ { "name": "headers", "$ref": "Headers", "description": "HTTP request headers." }
+ ]
+ },
+ {
+ "id": "WebSocketResponse",
+ "type": "object",
+ "description": "WebSocket response data.",
+ "hidden": true,
+ "properties": [
+ { "name": "status", "type": "number", "description": "HTTP response status code." },
+ { "name": "statusText", "type": "string", "description": "HTTP response status text." },
+ { "name": "headers", "$ref": "Headers", "description": "HTTP response headers." },
+ { "name": "headersText", "type": "string", "optional": true, "description": "HTTP response headers text." },
+ { "name": "requestHeaders", "$ref": "Headers", "optional": true, "description": "HTTP request headers." },
+ { "name": "requestHeadersText", "type": "string", "optional": true, "description": "HTTP request headers text." }
+ ]
+ },
+ {
+ "id": "WebSocketFrame",
+ "type": "object",
+ "description": "WebSocket frame data.",
+ "hidden": true,
+ "properties": [
+ { "name": "opcode", "type": "number", "description": "WebSocket frame opcode." },
+ { "name": "mask", "type": "boolean", "description": "WebSocke frame mask." },
+ { "name": "payloadData", "type": "string", "description": "WebSocke frame payload data." }
+ ]
+ },
+ {
+ "id": "CachedResource",
+ "type": "object",
+ "description": "Information about the cached resource.",
+ "properties": [
+ { "name": "url", "type": "string", "description": "Resource URL. This is the url of the original network request." },
+ { "name": "type", "$ref": "Page.ResourceType", "description": "Type of this resource." },
+ { "name": "response", "$ref": "Response", "optional": true, "description": "Cached response data." },
+ { "name": "bodySize", "type": "number", "description": "Cached response body size." }
+ ]
+ },
+ {
+ "id": "Initiator",
+ "type": "object",
+ "description": "Information about the request initiator.",
+ "properties": [
+ { "name": "type", "type": "string", "enum": ["parser", "script", "other"], "description": "Type of this initiator." },
+ { "name": "stack", "$ref": "Runtime.StackTrace", "optional": true, "description": "Initiator JavaScript stack trace, set for Script only." },
+ { "name": "url", "type": "string", "optional": true, "description": "Initiator URL, set for Parser type only." },
+ { "name": "lineNumber", "type": "number", "optional": true, "description": "Initiator line number, set for Parser type only." }
+ ]
+ },
+ {
+ "id": "Cookie",
+ "type": "object",
+ "description": "Cookie object",
+ "properties": [
+ { "name": "name", "type": "string", "description": "Cookie name." },
+ { "name": "value", "type": "string", "description": "Cookie value." },
+ { "name": "domain", "type": "string", "description": "Cookie domain." },
+ { "name": "path", "type": "string", "description": "Cookie path." },
+ { "name": "expires", "type": "number", "description": "Cookie expires." },
+ { "name": "size", "type": "integer", "description": "Cookie size." },
+ { "name": "httpOnly", "type": "boolean", "description": "True if cookie is http-only." },
+ { "name": "secure", "type": "boolean", "description": "True if cookie is secure." },
+ { "name": "session", "type": "boolean", "description": "True in case of session cookie." },
+ { "name": "sameSite", "type": "string", "optional": true, "enum": ["Strict", "Lax"], "description": "Represents the cookies' 'SameSite' status: https://tools.ietf.org/html/draft-west-first-party-cookies" }
+ ],
+ "hidden": true
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables network tracking, network events will now be delivered to the client.",
+ "parameters": [
+ { "name": "maxTotalBufferSize", "type": "integer", "optional": true, "hidden": true, "description": "Buffer size in bytes to use when preserving network payloads (XHRs, etc)." },
+ { "name": "maxResourceBufferSize", "type": "integer", "optional": true, "hidden": true, "description": "Per-resource buffer size in bytes to use when preserving network payloads (XHRs, etc)." }
+ ]
+ },
+ {
+ "name": "disable",
+ "description": "Disables network tracking, prevents network events from being sent to the client."
+ },
+ {
+ "name": "setUserAgentOverride",
+ "description": "Allows overriding user agent with the given string.",
+ "parameters": [
+ { "name": "userAgent", "type": "string", "description": "User agent to use." }
+ ]
+ },
+ {
+ "name": "setExtraHTTPHeaders",
+ "description": "Specifies whether to always send extra HTTP headers with the requests from this page.",
+ "parameters": [
+ { "name": "headers", "$ref": "Headers", "description": "Map with extra HTTP headers." }
+ ]
+ },
+ {
+ "name": "getResponseBody",
+ "async": true,
+ "description": "Returns content served for the given request.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Identifier of the network request to get content for." }
+ ],
+ "returns": [
+ { "name": "body", "type": "string", "description": "Response body." },
+ { "name": "base64Encoded", "type": "boolean", "description": "True, if content was sent as base64." }
+ ]
+ },
+ {
+ "name": "addBlockedURL",
+ "description": "Blocks specific URL from loading.",
+ "parameters": [
+ { "name": "url", "type": "string", "description": "URL to block." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "removeBlockedURL",
+ "description": "Cancels blocking of a specific URL from loading.",
+ "parameters": [
+ { "name": "url", "type": "string", "description": "URL to stop blocking." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "replayXHR",
+ "description": "This method sends a new XMLHttpRequest which is identical to the original one. The following parameters should be identical: method, url, async, request body, extra headers, withCredentials attribute, user, password.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Identifier of XHR to replay." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "setMonitoringXHREnabled",
+ "parameters": [
+ { "name": "enabled", "type": "boolean", "description": "Monitoring enabled state." }
+ ],
+ "description": "Toggles monitoring of XMLHttpRequest. If <code>true</code>, console will receive messages upon each XHR issued.",
+ "hidden": true
+ },
+ {
+ "name": "canClearBrowserCache",
+ "description": "Tells whether clearing browser cache is supported.",
+ "returns": [
+ { "name": "result", "type": "boolean", "description": "True if browser cache can be cleared." }
+ ]
+ },
+ {
+ "name": "clearBrowserCache",
+ "description": "Clears browser cache.",
+ "handlers": ["browser"]
+ },
+ {
+ "name": "canClearBrowserCookies",
+ "description": "Tells whether clearing browser cookies is supported.",
+ "returns": [
+ { "name": "result", "type": "boolean", "description": "True if browser cookies can be cleared." }
+ ]
+ },
+ {
+ "name": "clearBrowserCookies",
+ "description": "Clears browser cookies.",
+ "handlers": ["browser"]
+ },
+ {
+ "name": "getCookies",
+ "returns": [
+ { "name": "cookies", "type": "array", "items": { "$ref": "Cookie" }, "description": "Array of cookie objects." }
+ ],
+ "description": "Returns all browser cookies. Depending on the backend support, will return detailed cookie information in the <code>cookies</code> field.",
+ "handlers": ["browser"],
+ "async": true,
+ "hidden": true
+ },
+ {
+ "name": "deleteCookie",
+ "parameters": [
+ { "name": "cookieName", "type": "string", "description": "Name of the cookie to remove." },
+ { "name": "url", "type": "string", "description": "URL to match cooke domain and path." }
+ ],
+ "description": "Deletes browser cookie with given name, domain and path.",
+ "handlers": ["browser"],
+ "async": true,
+ "hidden": true
+ },
+ {
+ "name": "canEmulateNetworkConditions",
+ "description": "Tells whether emulation of network conditions is supported.",
+ "returns": [
+ { "name": "result", "type": "boolean", "description": "True if emulation of network conditions is supported." }
+ ],
+ "hidden": true,
+ "handlers": ["browser"]
+ },
+ {
+ "name": "emulateNetworkConditions",
+ "description": "Activates emulation of network conditions.",
+ "parameters": [
+ { "name": "offline", "type": "boolean", "description": "True to emulate internet disconnection." },
+ { "name": "latency", "type": "number", "description": "Additional latency (ms)." },
+ { "name": "downloadThroughput", "type": "number", "description": "Maximal aggregated download throughput." },
+ { "name": "uploadThroughput", "type": "number", "description": "Maximal aggregated upload throughput." }
+ ],
+ "hidden": true,
+ "handlers": ["browser", "renderer"]
+ },
+ {
+ "name": "setCacheDisabled",
+ "parameters": [
+ { "name": "cacheDisabled", "type": "boolean", "description": "Cache disabled state." }
+ ],
+ "description": "Toggles ignoring cache for each request. If <code>true</code>, cache will not be used."
+ },
+ {
+ "name": "setBypassServiceWorker",
+ "parameters": [
+ { "name": "bypass", "type": "boolean", "description": "Bypass service worker and load from network." }
+ ],
+ "hidden": true,
+ "description": "Toggles ignoring of service worker for each request."
+ },
+ {
+ "name": "setDataSizeLimitsForTest",
+ "parameters": [
+ { "name": "maxTotalSize", "type": "integer", "description": "Maximum total buffer size." },
+ { "name": "maxResourceSize", "type": "integer", "description": "Maximum per-resource size." }
+ ],
+ "description": "For testing.",
+ "hidden": true
+ },
+ {
+ "name": "getCertificateDetails",
+ "description": "Returns details for the given certificate.",
+ "parameters": [
+ { "name": "certificateId", "$ref": "CertificateId", "description": "ID of the certificate to get details for." }
+ ],
+ "returns": [
+ { "name": "result", "$ref": "CertificateDetails", "description": "Certificate details." }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "showCertificateViewer",
+ "description": "Displays native dialog with the certificate details.",
+ "parameters": [
+ { "name": "certificateId", "$ref": "CertificateId", "description": "Certificate id." }
+ ],
+ "handlers": ["browser"]
+ }
+ ],
+ "events": [
+ {
+ "name": "resourceChangedPriority",
+ "description": "Fired when resource loading priority is changed",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "newPriority", "$ref": "ResourcePriority", "description": "New priority" },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "requestWillBeSent",
+ "description": "Fired when page is about to send HTTP request.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "frameId", "$ref": "Page.FrameId", "description": "Frame identifier.", "hidden": true },
+ { "name": "loaderId", "$ref": "LoaderId", "description": "Loader identifier." },
+ { "name": "documentURL", "type": "string", "description": "URL of the document this request is loaded for." },
+ { "name": "request", "$ref": "Request", "description": "Request data." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
+ { "name": "wallTime", "$ref": "Timestamp", "hidden": true, "description": "UTC Timestamp." },
+ { "name": "initiator", "$ref": "Initiator", "description": "Request initiator." },
+ { "name": "redirectResponse", "optional": true, "$ref": "Response", "description": "Redirect response data." },
+ { "name": "type", "$ref": "Page.ResourceType", "optional": true, "hidden": true, "description": "Type of this resource." }
+ ]
+ },
+ {
+ "name": "requestServedFromCache",
+ "description": "Fired if request ended up loading from cache.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." }
+ ]
+ },
+ {
+ "name": "responseReceived",
+ "description": "Fired when HTTP response is available.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "frameId", "$ref": "Page.FrameId", "description": "Frame identifier.", "hidden": true },
+ { "name": "loaderId", "$ref": "LoaderId", "description": "Loader identifier." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
+ { "name": "type", "$ref": "Page.ResourceType", "description": "Resource type." },
+ { "name": "response", "$ref": "Response", "description": "Response data." }
+ ]
+ },
+ {
+ "name": "dataReceived",
+ "description": "Fired when data chunk was received over the network.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
+ { "name": "dataLength", "type": "integer", "description": "Data chunk length." },
+ { "name": "encodedDataLength", "type": "integer", "description": "Actual bytes received (might be less than dataLength for compressed encodings)." }
+ ]
+ },
+ {
+ "name": "loadingFinished",
+ "description": "Fired when HTTP request has finished loading.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
+ { "name": "encodedDataLength", "type": "number", "description": "Total number of bytes received for this request." }
+ ]
+ },
+ {
+ "name": "loadingFailed",
+ "description": "Fired when HTTP request has failed to load.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
+ { "name": "type", "$ref": "Page.ResourceType", "description": "Resource type." },
+ { "name": "errorText", "type": "string", "description": "User friendly error message." },
+ { "name": "canceled", "type": "boolean", "optional": true, "description": "True if loading was canceled." },
+ { "name": "blockedReason", "$ref": "BlockedReason", "optional": true, "description": "The reason why loading was blocked, if any.", "hidden": true }
+ ]
+ },
+ {
+ "name": "webSocketWillSendHandshakeRequest",
+ "description": "Fired when WebSocket is about to initiate handshake.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
+ { "name": "wallTime", "$ref": "Timestamp", "hidden": true, "description": "UTC Timestamp." },
+ { "name": "request", "$ref": "WebSocketRequest", "description": "WebSocket request data." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "webSocketHandshakeResponseReceived",
+ "description": "Fired when WebSocket handshake response becomes available.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
+ { "name": "response", "$ref": "WebSocketResponse", "description": "WebSocket response data." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "webSocketCreated",
+ "description": "Fired upon WebSocket creation.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "url", "type": "string", "description": "WebSocket request URL." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "webSocketClosed",
+ "description": "Fired when WebSocket is closed.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "webSocketFrameReceived",
+ "description": "Fired when WebSocket frame is received.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
+ { "name": "response", "$ref": "WebSocketFrame", "description": "WebSocket response data." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "webSocketFrameError",
+ "description": "Fired when WebSocket frame error occurs.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
+ { "name": "errorMessage", "type": "string", "description": "WebSocket frame error message." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "webSocketFrameSent",
+ "description": "Fired when WebSocket frame is sent.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
+ { "name": "response", "$ref": "WebSocketFrame", "description": "WebSocket response data." }
+ ],
+ "hidden": true
+ },
+ {
+ "name": "eventSourceMessageReceived",
+ "description": "Fired when EventSource message is received.",
+ "parameters": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier." },
+ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
+ { "name": "eventName", "type": "string", "description": "Message type." },
+ { "name": "eventId", "type": "string", "description": "Message identifier." },
+ { "name": "data", "type": "string", "description": "Message content." }
+ ],
+ "hidden": true
+ }
+ ]
+ },
+ {
+ "domain": "Database",
+ "hidden": true,
+ "types": [
+ {
+ "id": "DatabaseId",
+ "type": "string",
+ "description": "Unique identifier of Database object.",
+ "hidden": true
+ },
+ {
+ "id": "Database",
+ "type": "object",
+ "description": "Database object.",
+ "hidden": true,
+ "properties": [
+ { "name": "id", "$ref": "DatabaseId", "description": "Database ID." },
+ { "name": "domain", "type": "string", "description": "Database domain." },
+ { "name": "name", "type": "string", "description": "Database name." },
+ { "name": "version", "type": "string", "description": "Database version." }
+ ]
+ },
+ {
+ "id": "Error",
+ "type": "object",
+ "description": "Database error.",
+ "properties": [
+ { "name": "message", "type": "string", "description": "Error message." },
+ { "name": "code", "type": "integer", "description": "Error code." }
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables database tracking, database events will now be delivered to the client."
+ },
+ {
+ "name": "disable",
+ "description": "Disables database tracking, prevents database events from being sent to the client."
+ },
+ {
+ "name": "getDatabaseTableNames",
+ "parameters": [
+ { "name": "databaseId", "$ref": "DatabaseId" }
+ ],
+ "returns": [
+ { "name": "tableNames", "type": "array", "items": { "type": "string" } }
+ ]
+ },
+ {
+ "name": "executeSQL",
+ "async": true,
+ "parameters": [
+ { "name": "databaseId", "$ref": "DatabaseId" },
+ { "name": "query", "type": "string" }
+ ],
+ "returns": [
+ { "name": "columnNames", "type": "array", "optional": true, "items": { "type": "string" } },
+ { "name": "values", "type": "array", "optional": true, "items": { "type": "any" }},
+ { "name": "sqlError", "$ref": "Error", "optional": true }
+ ]
+ }
+ ],
+ "events": [
+ {
+ "name": "addDatabase",
+ "parameters": [
+ { "name": "database", "$ref": "Database" }
+ ]
+ }
+ ]
+ },
+ {
+ "domain": "IndexedDB",
+ "hidden": true,
+ "types": [
+ {
+ "id": "DatabaseWithObjectStores",
+ "type": "object",
+ "description": "Database with an array of object stores.",
+ "properties": [
+ { "name": "name", "type": "string", "description": "Database name." },
+ { "name": "version", "type": "integer", "description": "Database version." },
+ { "name": "objectStores", "type": "array", "items": { "$ref": "ObjectStore" }, "description": "Object stores in this database." }
+ ]
+ },
+ {
+ "id": "ObjectStore",
+ "type": "object",
+ "description": "Object store.",
+ "properties": [
+ { "name": "name", "type": "string", "description": "Object store name." },
+ { "name": "keyPath", "$ref": "KeyPath", "description": "Object store key path." },
+ { "name": "autoIncrement", "type": "boolean", "description": "If true, object store has auto increment flag set." },
+ { "name": "indexes", "type": "array", "items": { "$ref": "ObjectStoreIndex" }, "description": "Indexes in this object store." }
+ ]
+ },
+ {
+ "id": "ObjectStoreIndex",
+ "type": "object",
+ "description": "Object store index.",
+ "properties": [
+ { "name": "name", "type": "string", "description": "Index name." },
+ { "name": "keyPath", "$ref": "KeyPath", "description": "Index key path." },
+ { "name": "unique", "type": "boolean", "description": "If true, index is unique." },
+ { "name": "multiEntry", "type": "boolean", "description": "If true, index allows multiple entries for a key." }
+ ]
+ },
+ {
+ "id": "Key",
+ "type": "object",
+ "description": "Key.",
+ "properties": [
+ { "name": "type", "type": "string", "enum": ["number", "string", "date", "array"], "description": "Key type." },
+ { "name": "number", "type": "number", "optional": true, "description": "Number value." },
+ { "name": "string", "type": "string", "optional": true, "description": "String value." },
+ { "name": "date", "type": "number", "optional": true, "description": "Date value." },
+ { "name": "array", "type": "array", "optional": true, "items": { "$ref": "Key" }, "description": "Array value." }
+ ]
+ },
+ {
+ "id": "KeyRange",
+ "type": "object",
+ "description": "Key range.",
+ "properties": [
+ { "name": "lower", "$ref": "Key", "optional": true, "description": "Lower bound." },
+ { "name": "upper", "$ref": "Key", "optional": true, "description": "Upper bound." },
+ { "name": "lowerOpen", "type": "boolean", "description": "If true lower bound is open." },
+ { "name": "upperOpen", "type": "boolean", "description": "If true upper bound is open." }
+ ]
+ },
+ {
+ "id": "DataEntry",
+ "type": "object",
+ "description": "Data entry.",
+ "properties": [
+ { "name": "key", "type": "string", "description": "JSON-stringified key object." },
+ { "name": "primaryKey", "type": "string", "description": "JSON-stringified primary key object." },
+ { "name": "value", "type": "string", "description": "JSON-stringified value object." }
+ ]
+ },
+ {
+ "id": "KeyPath",
+ "type": "object",
+ "description": "Key path.",
+ "properties": [
+ { "name": "type", "type": "string", "enum": ["null", "string", "array"], "description": "Key path type." },
+ { "name": "string", "type": "string", "optional": true, "description": "String value." },
+ { "name": "array", "type": "array", "optional": true, "items": { "type": "string" }, "description": "Array value." }
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables events from backend."
+ },
+ {
+ "name": "disable",
+ "description": "Disables events from backend."
+ },
+ {
+ "name": "requestDatabaseNames",
+ "async": true,
+ "parameters": [
+ { "name": "securityOrigin", "type": "string", "description": "Security origin." }
+ ],
+ "returns": [
+ { "name": "databaseNames", "type": "array", "items": { "type": "string" }, "description": "Database names for origin." }
+ ],
+ "description": "Requests database names for given security origin."
+ },
+ {
+ "name": "requestDatabase",
+ "async": true,
+ "parameters": [
+ { "name": "securityOrigin", "type": "string", "description": "Security origin." },
+ { "name": "databaseName", "type": "string", "description": "Database name." }
+ ],
+ "returns": [
+ { "name": "databaseWithObjectStores", "$ref": "DatabaseWithObjectStores", "description": "Database with an array of object stores." }
+ ],
+ "description": "Requests database with given name in given frame."
+ },
+ {
+ "name": "requestData",
+ "async": true,
+ "parameters": [
+ { "name": "securityOrigin", "type": "string", "description": "Security origin." },
+ { "name": "databaseName", "type": "string", "description": "Database name." },
+ { "name": "objectStoreName", "type": "string", "description": "Object store name." },
+ { "name": "indexName", "type": "string", "description": "Index name, empty string for object store data requests." },
+ { "name": "skipCount", "type": "integer", "description": "Number of records to skip." },
+ { "name": "pageSize", "type": "integer", "description": "Number of records to fetch." },
+ { "name": "keyRange", "$ref": "KeyRange", "optional": true, "description": "Key range." }
+ ],
+ "returns": [
+ { "name": "objectStoreDataEntries", "type": "array", "items": { "$ref": "DataEntry" }, "description": "Array of object store data entries." },
+ { "name": "hasMore", "type": "boolean", "description": "If true, there are more entries to fetch in the given range." }
+ ],
+ "description": "Requests data from object store or index."
+ },
+ {
+ "name": "clearObjectStore",
+ "async": true,
+ "parameters": [
+ { "name": "securityOrigin", "type": "string", "description": "Security origin." },
+ { "name": "databaseName", "type": "string", "description": "Database name." },
+ { "name": "objectStoreName", "type": "string", "description": "Object store name." }
+ ],
+ "returns": [
+ ],
+ "description": "Clears all entries from an object store."
+ }
+ ]
+ },
+ {
+ "domain": "CacheStorage",
+ "hidden": true,
+ "types": [
+ {
+ "id": "CacheId",
+ "type": "string",
+ "description": "Unique identifier of the Cache object."
+ },
+ {
+ "id": "DataEntry",
+ "type": "object",
+ "description": "Data entry.",
+ "properties": [
+ { "name": "request", "type": "string", "description": "Request url spec." },
+ { "name": "response", "type": "string", "description": "Response stataus text." }
+ ]
+ },
+ {
+ "id": "Cache",
+ "type": "object",
+ "description": "Cache identifier.",
+ "properties": [
+ { "name": "cacheId", "$ref": "CacheId", "description": "An opaque unique id of the cache." },
+ { "name": "securityOrigin", "type": "string", "description": "Security origin of the cache." },
+ { "name": "cacheName", "type": "string", "description": "The name of the cache." }
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "requestCacheNames",
+ "async": true,
+ "parameters": [
+ { "name": "securityOrigin", "type": "string", "description": "Security origin." }
+ ],
+ "returns": [
+ { "name": "caches", "type": "array", "items": { "$ref": "Cache" }, "description": "Caches for the security origin." }
+ ],
+ "description": "Requests cache names."
+ },
+ {
+ "name": "requestEntries",
+ "async": true,
+ "parameters": [
+ { "name": "cacheId", "$ref": "CacheId", "description": "ID of cache to get entries from." },
+ { "name": "skipCount", "type": "integer", "description": "Number of records to skip." },
+ { "name": "pageSize", "type": "integer", "description": "Number of records to fetch." }
+ ],
+ "returns": [
+ { "name": "cacheDataEntries", "type": "array", "items": { "$ref": "DataEntry" }, "description": "Array of object store data entries." },
+ { "name": "hasMore", "type": "boolean", "description": "If true, there are more entries to fetch in the given range." }
+ ],
+ "description": "Requests data from cache."
+ },
+ {
+ "name": "deleteCache",
+ "async": true,
+ "parameters": [
+ { "name": "cacheId", "$ref": "CacheId", "description": "Id of cache for deletion." }
+ ],
+ "description": "Deletes a cache."
+ },
+ {
+ "name": "deleteEntry",
+ "async": true,
+ "parameters": [
+ { "name": "cacheId", "$ref": "CacheId", "description": "Id of cache where the entry will be deleted." },
+ { "name": "request", "type": "string", "description": "URL spec of the request." }
+ ],
+ "description": "Deletes a cache entry."
+ }
+ ]
+ },
+ {
+ "domain": "DOMStorage",
+ "hidden": true,
+ "description": "Query and modify DOM storage.",
+ "types": [
+ {
+ "id": "StorageId",
+ "type": "object",
+ "description": "DOM Storage identifier.",
+ "hidden": true,
+ "properties": [
+ { "name": "securityOrigin", "type": "string", "description": "Security origin for the storage." },
+ { "name": "isLocalStorage", "type": "boolean", "description": "Whether the storage is local storage (not session storage)." }
+ ]
+ },
+ {
+ "id": "Item",
+ "type": "array",
+ "description": "DOM Storage item.",
+ "hidden": true,
+ "items": { "type": "string" }
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables storage tracking, storage events will now be delivered to the client."
+ },
+ {
+ "name": "disable",
+ "description": "Disables storage tracking, prevents storage events from being sent to the client."
+ },
+ {
+ "name": "getDOMStorageItems",
+ "parameters": [
+ { "name": "storageId", "$ref": "StorageId" }
+ ],
+ "returns": [
+ { "name": "entries", "type": "array", "items": { "$ref": "Item" } }
+ ]
+ },
+ {
+ "name": "setDOMStorageItem",
+ "parameters": [
+ { "name": "storageId", "$ref": "StorageId" },
+ { "name": "key", "type": "string" },
+ { "name": "value", "type": "string" }
+ ]
+ },
+ {
+ "name": "removeDOMStorageItem",
+ "parameters": [
+ { "name": "storageId", "$ref": "StorageId" },
+ { "name": "key", "type": "string" }
+ ]
+ }
+ ],
+ "events": [
+ {
+ "name": "domStorageItemsCleared",
+ "parameters": [
+ { "name": "storageId", "$ref": "StorageId" }
+ ]
+ },
+ {
+ "name": "domStorageItemRemoved",
+ "parameters": [
+ { "name": "storageId", "$ref": "StorageId" },
+ { "name": "key", "type": "string" }
+ ]
+ },
+ {
+ "name": "domStorageItemAdded",
+ "parameters": [
+ { "name": "storageId", "$ref": "StorageId" },
+ { "name": "key", "type": "string" },
+ { "name": "newValue", "type": "string" }
+ ]
+ },
+ {
+ "name": "domStorageItemUpdated",
+ "parameters": [
+ { "name": "storageId", "$ref": "StorageId" },
+ { "name": "key", "type": "string" },
+ { "name": "oldValue", "type": "string" },
+ { "name": "newValue", "type": "string" }
+ ]
+ }
+ ]
+ },
+ {
+ "domain": "ApplicationCache",
+ "hidden": true,
+ "types": [
+ {
+ "id": "ApplicationCacheResource",
+ "type": "object",
+ "description": "Detailed application cache resource information.",
+ "properties": [
+ { "name": "url", "type": "string", "description": "Resource url." },
+ { "name": "size", "type": "integer", "description": "Resource size." },
+ { "name": "type", "type": "string", "description": "Resource type." }
+ ]
+ },
+ {
+ "id": "ApplicationCache",
+ "type": "object",
+ "description": "Detailed application cache information.",
+ "properties": [
+ { "name": "manifestURL", "type": "string", "description": "Manifest URL." },
+ { "name": "size", "type": "number", "description": "Application cache size." },
+ { "name": "creationTime", "type": "number", "description": "Application cache creation time." },
+ { "name": "updateTime", "type": "number", "description": "Application cache update time." },
+ { "name": "resources", "type": "array", "items": { "$ref": "ApplicationCacheResource" }, "description": "Application cache resources." }
+ ]
+ },
+ {
+ "id": "FrameWithManifest",
+ "type": "object",
+ "description": "Frame identifier - manifest URL pair.",
+ "properties": [
+ { "name": "frameId", "$ref": "Page.FrameId", "description": "Frame identifier." },
+ { "name": "manifestURL", "type": "string", "description": "Manifest URL." },
+ { "name": "status", "type": "integer", "description": "Application cache status." }
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "getFramesWithManifests",
+ "returns": [
+ { "name": "frameIds", "type": "array", "items": { "$ref": "FrameWithManifest" }, "description": "Array of frame identifiers with manifest urls for each frame containing a document associated with some application cache." }
+ ],
+ "description": "Returns array of frame identifiers with manifest urls for each frame containing a document associated with some application cache."
+ },
+ {
+ "name": "enable",
+ "description": "Enables application cache domain notifications."
+ },
+ {
+ "name": "getManifestForFrame",
+ "parameters": [
+ { "name": "frameId", "$ref": "Page.FrameId", "description": "Identifier of the frame containing document whose manifest is retrieved." }
+ ],
+ "returns": [
+ { "name": "manifestURL", "type": "string", "description": "Manifest URL for document in the given frame." }
+ ],
+ "description": "Returns manifest URL for document in the given frame."
+ },
+ {
+ "name": "getApplicationCacheForFrame",
+ "parameters": [
+ { "name": "frameId", "$ref": "Page.FrameId", "description": "Identifier of the frame containing document whose application cache is retrieved." }
+ ],
+ "returns": [
+ { "name": "applicationCache", "$ref": "ApplicationCache", "description": "Relevant application cache data for the document in given frame." }
+ ],
+ "description": "Returns relevant application cache data for the document in given frame."
+ }
+ ],
+ "events": [
+ {
+ "name": "applicationCacheStatusUpdated",
+ "parameters": [
+ { "name": "frameId", "$ref": "Page.FrameId", "description": "Identifier of the frame containing document whose application cache updated status." },
+ { "name": "manifestURL", "type": "string", "description": "Manifest URL." },
+ { "name": "status", "type": "integer", "description": "Updated application cache status." }
+ ]
+ },
+ {
+ "name": "networkStateUpdated",
+ "parameters": [
+ { "name": "isNowOnline", "type": "boolean" }
+ ]
+ }
+ ]
+ },
+ {
+ "domain": "DOM",
+ "description": "This domain exposes DOM read/write operations. Each DOM Node is represented with its mirror object that has an <code>id</code>. This <code>id</code> can be used to get additional information on the Node, resolve it into the JavaScript object wrapper, etc. It is important that client receives DOM events only for the nodes that are known to the client. Backend keeps track of the nodes that were sent to the client and never sends the same node twice. It is client's responsibility to collect information about the nodes that were sent to the client.<p>Note that <code>iframe</code> owner elements will return corresponding document elements as their child nodes.</p>",
+ "types": [
+ {
+ "id": "NodeId",
+ "type": "integer",
+ "description": "Unique DOM node identifier."
+ },
+ {
+ "id": "BackendNodeId",
+ "type": "integer",
+ "description": "Unique DOM node identifier used to reference a node that may not have been pushed to the front-end.",
+ "hidden": true
+ },
+ {
+ "id": "BackendNode",
+ "type": "object",
+ "properties": [
+ { "name": "nodeType", "type": "integer", "description": "<code>Node</code>'s nodeType." },
+ { "name": "nodeName", "type": "string", "description": "<code>Node</code>'s nodeName." },
+ { "name": "backendNodeId", "$ref": "BackendNodeId" }
+ ],
+ "hidden": true,
+ "description": "Backend node with a friendly name."
+ },
+ {
+ "id": "PseudoType",
+ "type": "string",
+ "enum": [
+ "first-line",
+ "first-letter",
+ "before",
+ "after",
+ "backdrop",
+ "selection",
+ "first-line-inherited",
+ "scrollbar",
+ "scrollbar-thumb",
+ "scrollbar-button",
+ "scrollbar-track",
+ "scrollbar-track-piece",
+ "scrollbar-corner",
+ "resizer",
+ "input-list-button"
+ ],
+ "description": "Pseudo element type."
+ },
+ {
+ "id": "ShadowRootType",
+ "type": "string",
+ "enum": ["user-agent", "open", "closed"],
+ "description": "Shadow root type."
+ },
+ {
+ "id": "Node",
+ "type": "object",
+ "properties": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Node identifier that is passed into the rest of the DOM messages as the <code>nodeId</code>. Backend will only push node with given <code>id</code> once. It is aware of all requested nodes and will only fire DOM events for nodes known to the client." },
+ { "name": "nodeType", "type": "integer", "description": "<code>Node</code>'s nodeType." },
+ { "name": "nodeName", "type": "string", "description": "<code>Node</code>'s nodeName." },
+ { "name": "localName", "type": "string", "description": "<code>Node</code>'s localName." },
+ { "name": "nodeValue", "type": "string", "description": "<code>Node</code>'s nodeValue." },
+ { "name": "childNodeCount", "type": "integer", "optional": true, "description": "Child count for <code>Container</code> nodes." },
+ { "name": "children", "type": "array", "optional": true, "items": { "$ref": "Node" }, "description": "Child nodes of this node when requested with children." },
+ { "name": "attributes", "type": "array", "optional": true, "items": { "type": "string" }, "description": "Attributes of the <code>Element</code> node in the form of flat array <code>[name1, value1, name2, value2]</code>." },
+ { "name": "documentURL", "type": "string", "optional": true, "description": "Document URL that <code>Document</code> or <code>FrameOwner</code> node points to." },
+ { "name": "baseURL", "type": "string", "optional": true, "description": "Base URL that <code>Document</code> or <code>FrameOwner</code> node uses for URL completion.", "hidden": true },
+ { "name": "publicId", "type": "string", "optional": true, "description": "<code>DocumentType</code>'s publicId." },
+ { "name": "systemId", "type": "string", "optional": true, "description": "<code>DocumentType</code>'s systemId." },
+ { "name": "internalSubset", "type": "string", "optional": true, "description": "<code>DocumentType</code>'s internalSubset." },
+ { "name": "xmlVersion", "type": "string", "optional": true, "description": "<code>Document</code>'s XML version in case of XML documents." },
+ { "name": "name", "type": "string", "optional": true, "description": "<code>Attr</code>'s name." },
+ { "name": "value", "type": "string", "optional": true, "description": "<code>Attr</code>'s value." },
+ { "name": "pseudoType", "$ref": "PseudoType", "optional": true, "description": "Pseudo element type for this node." },
+ { "name": "shadowRootType", "$ref": "ShadowRootType", "optional": true, "description": "Shadow root type." },
+ { "name": "frameId", "$ref": "Page.FrameId", "optional": true, "description": "Frame ID for frame owner elements.", "hidden": true },
+ { "name": "contentDocument", "$ref": "Node", "optional": true, "description": "Content document for frame owner elements." },
+ { "name": "shadowRoots", "type": "array", "optional": true, "items": { "$ref": "Node" }, "description": "Shadow root list for given element host.", "hidden": true },
+ { "name": "templateContent", "$ref": "Node", "optional": true, "description": "Content document fragment for template elements.", "hidden": true },
+ { "name": "pseudoElements", "type": "array", "items": { "$ref": "Node" }, "optional": true, "description": "Pseudo elements associated with this node.", "hidden": true },
+ { "name": "importedDocument", "$ref": "Node", "optional": true, "description": "Import document for the HTMLImport links." },
+ { "name": "distributedNodes", "type": "array", "items": { "$ref": "BackendNode" }, "optional": true, "description": "Distributed nodes for given insertion point.", "hidden": true }
+ ],
+ "description": "DOM interaction is implemented in terms of mirror objects that represent the actual DOM nodes. DOMNode is a base node mirror type."
+ },
+ {
+ "id": "RGBA",
+ "type": "object",
+ "properties": [
+ { "name": "r", "type": "integer", "description": "The red component, in the [0-255] range." },
+ { "name": "g", "type": "integer", "description": "The green component, in the [0-255] range." },
+ { "name": "b", "type": "integer", "description": "The blue component, in the [0-255] range." },
+ { "name": "a", "type": "number", "optional": true, "description": "The alpha component, in the [0-1] range (default: 1)." }
+ ],
+ "description": "A structure holding an RGBA color."
+ },
+ {
+ "id": "Quad",
+ "type": "array",
+ "items": { "type": "number" },
+ "minItems": 8,
+ "maxItems": 8,
+ "description": "An array of quad vertices, x immediately followed by y for each point, points clock-wise.",
+ "hidden": true
+ },
+ {
+ "id": "BoxModel",
+ "type": "object",
+ "hidden": true,
+ "properties": [
+ { "name": "content", "$ref": "Quad", "description": "Content box" },
+ { "name": "padding", "$ref": "Quad", "description": "Padding box" },
+ { "name": "border", "$ref": "Quad", "description": "Border box" },
+ { "name": "margin", "$ref": "Quad", "description": "Margin box" },
+ { "name": "width", "type": "integer", "description": "Node width" },
+ { "name": "height", "type": "integer", "description": "Node height" },
+ { "name": "shapeOutside", "$ref": "ShapeOutsideInfo", "optional": true, "description": "Shape outside coordinates" }
+ ],
+ "description": "Box model."
+ },
+ {
+ "id": "ShapeOutsideInfo",
+ "type": "object",
+ "hidden": true,
+ "properties": [
+ { "name": "bounds", "$ref": "Quad", "description": "Shape bounds" },
+ { "name": "shape", "type": "array", "items": { "type": "any"}, "description": "Shape coordinate details" },
+ { "name": "marginShape", "type": "array", "items": { "type": "any"}, "description": "Margin shape bounds" }
+ ],
+ "description": "CSS Shape Outside details."
+ },
+ {
+ "id": "Rect",
+ "type": "object",
+ "hidden": true,
+ "properties": [
+ { "name": "x", "type": "number", "description": "X coordinate" },
+ { "name": "y", "type": "number", "description": "Y coordinate" },
+ { "name": "width", "type": "number", "description": "Rectangle width" },
+ { "name": "height", "type": "number", "description": "Rectangle height" }
+ ],
+ "description": "Rectangle."
+ },
+ {
+ "id": "HighlightConfig",
+ "type": "object",
+ "properties": [
+ { "name": "showInfo", "type": "boolean", "optional": true, "description": "Whether the node info tooltip should be shown (default: false)." },
+ { "name": "showRulers", "type": "boolean", "optional": true, "description": "Whether the rulers should be shown (default: false)." },
+ { "name": "showExtensionLines", "type": "boolean", "optional": true, "description": "Whether the extension lines from node to the rulers should be shown (default: false)." },
+ { "name": "displayAsMaterial", "type": "boolean", "optional": true, "hidden": true},
+ { "name": "contentColor", "$ref": "RGBA", "optional": true, "description": "The content box highlight fill color (default: transparent)." },
+ { "name": "paddingColor", "$ref": "RGBA", "optional": true, "description": "The padding highlight fill color (default: transparent)." },
+ { "name": "borderColor", "$ref": "RGBA", "optional": true, "description": "The border highlight fill color (default: transparent)." },
+ { "name": "marginColor", "$ref": "RGBA", "optional": true, "description": "The margin highlight fill color (default: transparent)." },
+ { "name": "eventTargetColor", "$ref": "RGBA", "optional": true, "hidden": true, "description": "The event target element highlight fill color (default: transparent)." },
+ { "name": "shapeColor", "$ref": "RGBA", "optional": true, "hidden": true, "description": "The shape outside fill color (default: transparent)." },
+ { "name": "shapeMarginColor", "$ref": "RGBA", "optional": true, "hidden": true, "description": "The shape margin fill color (default: transparent)." },
+ { "name": "selectorList", "type": "string", "optional": true, "description": "Selectors to highlight relevant nodes."}
+ ],
+ "description": "Configuration data for the highlighting of page elements."
+ },
+ {
+ "id": "InspectMode",
+ "type": "string",
+ "hidden": true,
+ "enum": [
+ "searchForNode",
+ "searchForUAShadowDOM",
+ "showLayoutEditor",
+ "none"
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables DOM agent for the given page."
+ },
+ {
+ "name": "disable",
+ "description": "Disables DOM agent for the given page."
+ },
+ {
+ "name": "getDocument",
+ "returns": [
+ { "name": "root", "$ref": "Node", "description": "Resulting node." }
+ ],
+ "description": "Returns the root DOM node to the caller."
+ },
+ {
+ "name": "requestChildNodes",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to get children for." },
+ { "name": "depth", "type": "integer", "optional": true, "description": "The maximum depth at which children should be retrieved, defaults to 1. Use -1 for the entire subtree or provide an integer larger than 0.", "hidden": true }
+ ],
+ "description": "Requests that children of the node with given id are returned to the caller in form of <code>setChildNodes</code> events where not only immediate children are retrieved, but all children down to the specified depth."
+ },
+ {
+ "name": "querySelector",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to query upon." },
+ { "name": "selector", "type": "string", "description": "Selector string." }
+ ],
+ "returns": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Query selector result." }
+ ],
+ "description": "Executes <code>querySelector</code> on a given node."
+ },
+ {
+ "name": "querySelectorAll",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to query upon." },
+ { "name": "selector", "type": "string", "description": "Selector string." }
+ ],
+ "returns": [
+ { "name": "nodeIds", "type": "array", "items": { "$ref": "NodeId" }, "description": "Query selector result." }
+ ],
+ "description": "Executes <code>querySelectorAll</code> on a given node."
+ },
+ {
+ "name": "setNodeName",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to set name for." },
+ { "name": "name", "type": "string", "description": "New node's name." }
+ ],
+ "returns": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "New node's id." }
+ ],
+ "description": "Sets node name for a node with given id."
+ },
+ {
+ "name": "setNodeValue",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to set value for." },
+ { "name": "value", "type": "string", "description": "New node's value." }
+ ],
+ "description": "Sets node value for a node with given id."
+ },
+ {
+ "name": "removeNode",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to remove." }
+ ],
+ "description": "Removes node with given id."
+ },
+ {
+ "name": "setAttributeValue",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the element to set attribute for." },
+ { "name": "name", "type": "string", "description": "Attribute name." },
+ { "name": "value", "type": "string", "description": "Attribute value." }
+ ],
+ "description": "Sets attribute for an element with given id."
+ },
+ {
+ "name": "setAttributesAsText",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the element to set attributes for." },
+ { "name": "text", "type": "string", "description": "Text with a number of attributes. Will parse this text using HTML parser." },
+ { "name": "name", "type": "string", "optional": true, "description": "Attribute name to replace with new attributes derived from text in case text parsed successfully." }
+ ],
+ "description": "Sets attributes on element with given id. This method is useful when user edits some existing attribute value and types in several attribute name/value pairs."
+ },
+ {
+ "name": "removeAttribute",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the element to remove attribute from." },
+ { "name": "name", "type": "string", "description": "Name of the attribute to remove." }
+ ],
+ "description": "Removes attribute with given name from an element with given id."
+ },
+ {
+ "name": "getOuterHTML",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to get markup for." }
+ ],
+ "returns": [
+ { "name": "outerHTML", "type": "string", "description": "Outer HTML markup." }
+ ],
+ "description": "Returns node's HTML markup."
+ },
+ {
+ "name": "setOuterHTML",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to set markup for." },
+ { "name": "outerHTML", "type": "string", "description": "Outer HTML markup to set." }
+ ],
+ "description": "Sets node HTML markup, returns new node id."
+ },
+ {
+ "name": "performSearch",
+ "parameters": [
+ { "name": "query", "type": "string", "description": "Plain text or query selector or XPath search query." },
+ { "name": "includeUserAgentShadowDOM", "type": "boolean", "optional": true, "description": "True to search in user agent shadow DOM.", "hidden": true }
+ ],
+ "returns": [
+ { "name": "searchId", "type": "string", "description": "Unique search session identifier." },
+ { "name": "resultCount", "type": "integer", "description": "Number of search results." }
+ ],
+ "description": "Searches for a given string in the DOM tree. Use <code>getSearchResults</code> to access search results or <code>cancelSearch</code> to end this search session.",
+ "hidden": true
+ },
+ {
+ "name": "getSearchResults",
+ "parameters": [
+ { "name": "searchId", "type": "string", "description": "Unique search session identifier." },
+ { "name": "fromIndex", "type": "integer", "description": "Start index of the search result to be returned." },
+ { "name": "toIndex", "type": "integer", "description": "End index of the search result to be returned." }
+ ],
+ "returns": [
+ { "name": "nodeIds", "type": "array", "items": { "$ref": "NodeId" }, "description": "Ids of the search result nodes." }
+ ],
+ "description": "Returns search results from given <code>fromIndex</code> to given <code>toIndex</code> from the sarch with the given identifier.",
+ "hidden": true
+ },
+ {
+ "name": "discardSearchResults",
+ "parameters": [
+ { "name": "searchId", "type": "string", "description": "Unique search session identifier." }
+ ],
+ "description": "Discards search results from the session with the given id. <code>getSearchResults</code> should no longer be called for that search.",
+ "hidden": true
+ },
+ {
+ "name": "requestNode",
+ "parameters": [
+ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "JavaScript object id to convert into node." }
+ ],
+ "returns": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Node id for given object." }
+ ],
+ "description": "Requests that the node is sent to the caller given the JavaScript node object reference. All nodes that form the path from the node to the root are also sent to the client as a series of <code>setChildNodes</code> notifications."
+ },
+ {
+ "name": "setInspectMode",
+ "hidden": true,
+ "parameters": [
+ { "name": "mode", "$ref": "InspectMode", "description": "Set an inspection mode." },
+ { "name": "highlightConfig", "$ref": "HighlightConfig", "optional": true, "description": "A descriptor for the highlight appearance of hovered-over nodes. May be omitted if <code>enabled == false</code>." }
+ ],
+ "description": "Enters the 'inspect' mode. In this mode, elements that user is hovering over are highlighted. Backend then generates 'inspectNodeRequested' event upon element selection."
+ },
+ {
+ "name": "highlightRect",
+ "parameters": [
+ { "name": "x", "type": "integer", "description": "X coordinate" },
+ { "name": "y", "type": "integer", "description": "Y coordinate" },
+ { "name": "width", "type": "integer", "description": "Rectangle width" },
+ { "name": "height", "type": "integer", "description": "Rectangle height" },
+ { "name": "color", "$ref": "RGBA", "optional": true, "description": "The highlight fill color (default: transparent)." },
+ { "name": "outlineColor", "$ref": "RGBA", "optional": true, "description": "The highlight outline color (default: transparent)." }
+ ],
+ "description": "Highlights given rectangle. Coordinates are absolute with respect to the main frame viewport."
+ },
+ {
+ "name": "highlightQuad",
+ "parameters": [
+ { "name": "quad", "$ref": "Quad", "description": "Quad to highlight" },
+ { "name": "color", "$ref": "RGBA", "optional": true, "description": "The highlight fill color (default: transparent)." },
+ { "name": "outlineColor", "$ref": "RGBA", "optional": true, "description": "The highlight outline color (default: transparent)." }
+ ],
+ "description": "Highlights given quad. Coordinates are absolute with respect to the main frame viewport.",
+ "hidden": true
+ },
+ {
+ "name": "highlightNode",
+ "parameters": [
+ { "name": "highlightConfig", "$ref": "HighlightConfig", "description": "A descriptor for the highlight appearance." },
+ { "name": "nodeId", "$ref": "NodeId", "optional": true, "description": "Identifier of the node to highlight." },
+ { "name": "backendNodeId", "$ref": "BackendNodeId", "optional": true, "description": "Identifier of the backend node to highlight." },
+ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "optional": true, "description": "JavaScript object id of the node to be highlighted.", "hidden": true }
+ ],
+ "description": "Highlights DOM node with given id or with the given JavaScript object wrapper. Either nodeId or objectId must be specified."
+ },
+ {
+ "name": "hideHighlight",
+ "description": "Hides DOM node highlight."
+ },
+ {
+ "name": "highlightFrame",
+ "parameters": [
+ { "name": "frameId", "$ref": "Page.FrameId", "description": "Identifier of the frame to highlight." },
+ { "name": "contentColor", "$ref": "RGBA", "optional": true, "description": "The content box highlight fill color (default: transparent)." },
+ { "name": "contentOutlineColor", "$ref": "RGBA", "optional": true, "description": "The content box highlight outline color (default: transparent)." }
+ ],
+ "description": "Highlights owner element of the frame with given id.",
+ "hidden": true
+ },
+ {
+ "name": "pushNodeByPathToFrontend",
+ "parameters": [
+ { "name": "path", "type": "string", "description": "Path to node in the proprietary format." }
+ ],
+ "returns": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node for given path." }
+ ],
+ "description": "Requests that the node is sent to the caller given its path. // FIXME, use XPath",
+ "hidden": true
+ },
+ {
+ "name": "pushNodesByBackendIdsToFrontend",
+ "parameters": [
+ { "name": "backendNodeIds", "type": "array", "items": {"$ref": "BackendNodeId"}, "description": "The array of backend node ids." }
+ ],
+ "returns": [
+ { "name": "nodeIds", "type": "array", "items": {"$ref": "NodeId"}, "description": "The array of ids of pushed nodes that correspond to the backend ids specified in backendNodeIds." }
+ ],
+ "description": "Requests that a batch of nodes is sent to the caller given their backend node ids.",
+ "hidden": true
+ },
+ {
+ "name": "setInspectedNode",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "DOM node id to be accessible by means of $x command line API." }
+ ],
+ "description": "Enables console to refer to the node with given id via $x (see Command Line API for more details $x functions).",
+ "hidden": true
+ },
+ {
+ "name": "resolveNode",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to resolve." },
+ { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." }
+ ],
+ "returns": [
+ { "name": "object", "$ref": "Runtime.RemoteObject", "description": "JavaScript object wrapper for given node." }
+ ],
+ "description": "Resolves JavaScript node object for given node id."
+ },
+ {
+ "name": "getAttributes",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to retrieve attibutes for." }
+ ],
+ "returns": [
+ { "name": "attributes", "type": "array", "items": { "type": "string" }, "description": "An interleaved array of node attribute names and values." }
+ ],
+ "description": "Returns attributes for the specified node."
+ },
+ {
+ "name": "copyTo",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to copy." },
+ { "name": "targetNodeId", "$ref": "NodeId", "description": "Id of the element to drop the copy into." },
+ { "name": "insertBeforeNodeId", "$ref": "NodeId", "optional": true, "description": "Drop the copy before this node (if absent, the copy becomes the last child of <code>targetNodeId</code>)." }
+ ],
+ "returns": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node clone." }
+ ],
+ "description": "Creates a deep copy of the specified node and places it into the target container before the given anchor.",
+ "hidden": true
+ },
+ {
+ "name": "moveTo",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to move." },
+ { "name": "targetNodeId", "$ref": "NodeId", "description": "Id of the element to drop the moved node into." },
+ { "name": "insertBeforeNodeId", "$ref": "NodeId", "optional": true, "description": "Drop node before this one (if absent, the moved node becomes the last child of <code>targetNodeId</code>)." }
+ ],
+ "returns": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "New id of the moved node." }
+ ],
+ "description": "Moves node into the new container, places it before the given anchor."
+ },
+ {
+ "name": "undo",
+ "description": "Undoes the last performed action.",
+ "hidden": true
+ },
+ {
+ "name": "redo",
+ "description": "Re-does the last undone action.",
+ "hidden": true
+ },
+ {
+ "name": "markUndoableState",
+ "description": "Marks last undoable state.",
+ "hidden": true
+ },
+ {
+ "name": "focus",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to focus." }
+ ],
+ "description": "Focuses the given element.",
+ "hidden": true
+ },
+ {
+ "name": "setFileInputFiles",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the file input node to set files for." },
+ { "name": "files", "type": "array", "items": { "type": "string" }, "description": "Array of file paths to set." }
+ ],
+ "description": "Sets files for the given file input element.",
+ "hidden": true,
+ "handlers": ["browser", "renderer"]
+ },
+ {
+ "name": "getBoxModel",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to get box model for." }
+ ],
+ "returns": [
+ { "name": "model", "$ref": "BoxModel", "description": "Box model for the node." }
+ ],
+ "description": "Returns boxes for the currently selected nodes.",
+ "hidden": true
+ },
+ {
+ "name": "getNodeForLocation",
+ "parameters": [
+ { "name": "x", "type": "integer", "description": "X coordinate." },
+ { "name": "y", "type": "integer", "description": "Y coordinate." }
+ ],
+ "returns": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node at given coordinates." }
+ ],
+ "description": "Returns node id at given location.",
+ "hidden": true
+ },
+ {
+ "name": "getRelayoutBoundary",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node." }
+ ],
+ "returns": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Relayout boundary node id for the given node." }
+ ],
+ "description": "Returns the id of the nearest ancestor that is a relayout boundary.",
+ "hidden": true
+ },
+ {
+ "name": "getHighlightObjectForTest",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to get highlight object for." }
+ ],
+ "returns": [
+ { "name": "highlight", "type": "object", "description": "Highlight data for the node." }
+ ],
+ "description": "For testing.",
+ "hidden": true
+ }
+ ],
+ "events": [
+ {
+ "name": "documentUpdated",
+ "description": "Fired when <code>Document</code> has been totally updated. Node ids are no longer valid."
+ },
+ {
+ "name": "inspectNodeRequested",
+ "parameters": [
+ { "name": "backendNodeId", "$ref": "BackendNodeId", "description": "Id of the node to inspect." }
+ ],
+ "description": "Fired when the node should be inspected. This happens after call to <code>setInspectMode</code>.",
+ "hidden" : true
+ },
+ {
+ "name": "setChildNodes",
+ "parameters": [
+ { "name": "parentId", "$ref": "NodeId", "description": "Parent node id to populate with children." },
+ { "name": "nodes", "type": "array", "items": { "$ref": "Node" }, "description": "Child nodes array." }
+ ],
+ "description": "Fired when backend wants to provide client with the missing DOM structure. This happens upon most of the calls requesting node ids."
+ },
+ {
+ "name": "attributeModified",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node that has changed." },
+ { "name": "name", "type": "string", "description": "Attribute name." },
+ { "name": "value", "type": "string", "description": "Attribute value." }
+ ],
+ "description": "Fired when <code>Element</code>'s attribute is modified."
+ },
+ {
+ "name": "attributeRemoved",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node that has changed." },
+ { "name": "name", "type": "string", "description": "A ttribute name." }
+ ],
+ "description": "Fired when <code>Element</code>'s attribute is removed."
+ },
+ {
+ "name": "inlineStyleInvalidated",
+ "parameters": [
+ { "name": "nodeIds", "type": "array", "items": { "$ref": "NodeId" }, "description": "Ids of the nodes for which the inline styles have been invalidated." }
+ ],
+ "description": "Fired when <code>Element</code>'s inline style is modified via a CSS property modification.",
+ "hidden": true
+ },
+ {
+ "name": "characterDataModified",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node that has changed." },
+ { "name": "characterData", "type": "string", "description": "New text value." }
+ ],
+ "description": "Mirrors <code>DOMCharacterDataModified</code> event."
+ },
+ {
+ "name": "childNodeCountUpdated",
+ "parameters": [
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node that has changed." },
+ { "name": "childNodeCount", "type": "integer", "description": "New node count." }
+ ],
+ "description": "Fired when <code>Container</code>'s child node count has changed."
+ },
+ {
+ "name": "childNodeInserted",
+ "parameters": [
+ { "name": "parentNodeId", "$ref": "NodeId", "description": "Id of the node that has changed." },
+ { "name": "previousNodeId", "$ref": "NodeId", "description": "If of the previous siblint." },
+ { "name": "node", "$ref": "Node", "description": "Inserted node data." }
+ ],
+ "description": "Mirrors <code>DOMNodeInserted</code> event."
+ },
+ {
+ "name": "childNodeRemoved",
+ "parameters": [
+ { "name": "parentNodeId", "$ref": "NodeId", "description": "Parent id." },
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node that has been removed." }
+ ],
+ "description": "Mirrors <code>DOMNodeRemoved</code> event."
+ },
+ {
+ "name": "shadowRootPushed",
+ "parameters": [
+ { "name": "hostId", "$ref": "NodeId", "description": "Host element id." },
+ { "name": "root", "$ref": "Node", "description": "Shadow root." }
+ ],
+ "description": "Called when shadow root is pushed into the element.",
+ "hidden": true
+ },
+ {
+ "name": "shadowRootPopped",
+ "parameters": [
+ { "name": "hostId", "$ref": "NodeId", "description": "Host element id." },
+ { "name": "rootId", "$ref": "NodeId", "description": "Shadow root id." }
+ ],
+ "description": "Called when shadow root is popped from the element.",
+ "hidden": true
+ },
+ {
+ "name": "pseudoElementAdded",
+ "parameters": [
+ { "name": "parentId", "$ref": "NodeId", "description": "Pseudo element's parent element id." },
+ { "name": "pseudoElement", "$ref": "Node", "description": "The added pseudo element." }
+ ],
+ "description": "Called when a pseudo element is added to an element.",
+ "hidden": true
+ },
+ {
+ "name": "pseudoElementRemoved",
+ "parameters": [
+ { "name": "parentId", "$ref": "NodeId", "description": "Pseudo element's parent element id." },
+ { "name": "pseudoElementId", "$ref": "NodeId", "description": "The removed pseudo element id." }
+ ],
+ "description": "Called when a pseudo element is removed from an element.",
+ "hidden": true
+ },
+ {
+ "name": "distributedNodesUpdated",
+ "parameters": [
+ { "name": "insertionPointId", "$ref": "NodeId", "description": "Insertion point where distrubuted nodes were updated." },
+ { "name": "distributedNodes", "type": "array", "items": { "$ref": "BackendNode" }, "description": "Distributed nodes for given insertion point." }
+ ],
+ "description": "Called when distrubution is changed.",
+ "hidden": true
+ },
+ {
+ "name": "nodeHighlightRequested",
+ "parameters": [
+ {"name": "nodeId", "$ref": "NodeId"}
+ ],
+ "hidden": true
+ }
+ ]
+ },
+ {
+ "domain": "CSS",
+ "hidden": true,
+ "description": "This domain exposes CSS read/write operations. All CSS objects (stylesheets, rules, and styles) have an associated <code>id</code> used in subsequent operations on the related object. Each object type has a specific <code>id</code> structure, and those are not interchangeable between objects of different kinds. CSS objects can be loaded using the <code>get*ForNode()</code> calls (which accept a DOM node id). A client can also discover all the existing stylesheets with the <code>getAllStyleSheets()</code> method (or keeping track of the <code>styleSheetAdded</code>/<code>styleSheetRemoved</code> events) and subsequently load the required stylesheet contents using the <code>getStyleSheet[Text]()</code> methods.",
+ "types": [
+ {
+ "id": "StyleSheetId",
+ "type": "string"
+ },
+ {
+ "id": "StyleSheetOrigin",
+ "type": "string",
+ "enum": ["injected", "user-agent", "inspector", "regular"],
+ "description": "Stylesheet type: \"injected\" for stylesheets injected via extension, \"user-agent\" for user-agent stylesheets, \"inspector\" for stylesheets created by the inspector (i.e. those holding the \"via inspector\" rules), \"regular\" for regular stylesheets."
+ },
+ {
+ "id": "PseudoElementMatches",
+ "type": "object",
+ "properties": [
+ { "name": "pseudoType", "$ref": "DOM.PseudoType", "description": "Pseudo element type."},
+ { "name": "matches", "type": "array", "items": { "$ref": "RuleMatch" }, "description": "Matches of CSS rules applicable to the pseudo style."}
+ ],
+ "description": "CSS rule collection for a single pseudo style."
+ },
+ {
+ "id": "InheritedStyleEntry",
+ "type": "object",
+ "properties": [
+ { "name": "inlineStyle", "$ref": "CSSStyle", "optional": true, "description": "The ancestor node's inline style, if any, in the style inheritance chain." },
+ { "name": "matchedCSSRules", "type": "array", "items": { "$ref": "RuleMatch" }, "description": "Matches of CSS rules matching the ancestor node in the style inheritance chain." }
+ ],
+ "description": "Inherited CSS rule collection from ancestor node."
+ },
+ {
+ "id": "RuleMatch",
+ "type": "object",
+ "properties": [
+ { "name": "rule", "$ref": "CSSRule", "description": "CSS rule in the match." },
+ { "name": "matchingSelectors", "type": "array", "items": { "type": "integer" }, "description": "Matching selector indices in the rule's selectorList selectors (0-based)." }
+ ],
+ "description": "Match data for a CSS rule."
+ },
+ {
+ "id": "Value",
+ "type": "object",
+ "properties": [
+ { "name": "text", "type": "string", "description": "Value text." },
+ { "name": "range", "$ref": "SourceRange", "optional": true, "description": "Value range in the underlying resource (if available)." }
+ ],
+ "description": "Data for a simple selector (these are delimited by commas in a selector list)."
+ },
+ {
+ "id": "SelectorList",
+ "type": "object",
+ "properties": [
+ { "name": "selectors", "type": "array", "items": { "$ref": "Value" }, "description": "Selectors in the list." },
+ { "name": "text", "type": "string", "description": "Rule selector text." }
+ ],
+ "description": "Selector list data."
+ },
+ {
+ "id": "CSSStyleSheetHeader",
+ "type": "object",
+ "properties": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId", "description": "The stylesheet identifier."},
+ { "name": "frameId", "$ref": "Page.FrameId", "description": "Owner frame identifier."},
+ { "name": "sourceURL", "type": "string", "description": "Stylesheet resource URL."},
+ { "name": "sourceMapURL", "type": "string", "optional": true, "description": "URL of source map associated with the stylesheet (if any)." },
+ { "name": "origin", "$ref": "StyleSheetOrigin", "description": "Stylesheet origin."},
+ { "name": "title", "type": "string", "description": "Stylesheet title."},
+ { "name": "ownerNode", "$ref": "DOM.BackendNodeId", "optional": true, "description": "The backend id for the owner node of the stylesheet." },
+ { "name": "disabled", "type": "boolean", "description": "Denotes whether the stylesheet is disabled."},
+ { "name": "hasSourceURL", "type": "boolean", "optional": true, "description": "Whether the sourceURL field value comes from the sourceURL comment." },
+ { "name": "isInline", "type": "boolean", "description": "Whether this stylesheet is created for STYLE tag by parser. This flag is not set for document.written STYLE tags." },
+ { "name": "startLine", "type": "number", "description": "Line offset of the stylesheet within the resource (zero based)." },
+ { "name": "startColumn", "type": "number", "description": "Column offset of the stylesheet within the resource (zero based)." }
+ ],
+ "description": "CSS stylesheet metainformation."
+ },
+ {
+ "id": "CSSRule",
+ "type": "object",
+ "properties": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId", "optional": true, "description": "The css style sheet identifier (absent for user agent stylesheet and user-specified stylesheet rules) this rule came from." },
+ { "name": "selectorList", "$ref": "SelectorList", "description": "Rule selector data." },
+ { "name": "origin", "$ref": "StyleSheetOrigin", "description": "Parent stylesheet's origin."},
+ { "name": "style", "$ref": "CSSStyle", "description": "Associated style declaration." },
+ { "name": "media", "type": "array", "items": { "$ref": "CSSMedia" }, "optional": true, "description": "Media list array (for rules involving media queries). The array enumerates media queries starting with the innermost one, going outwards." }
+ ],
+ "description": "CSS rule representation."
+ },
+ {
+ "id": "SourceRange",
+ "type": "object",
+ "properties": [
+ { "name": "startLine", "type": "integer", "description": "Start line of range." },
+ { "name": "startColumn", "type": "integer", "description": "Start column of range (inclusive)." },
+ { "name": "endLine", "type": "integer", "description": "End line of range" },
+ { "name": "endColumn", "type": "integer", "description": "End column of range (exclusive)." }
+ ],
+ "description": "Text range within a resource. All numbers are zero-based."
+ },
+ {
+ "id": "ShorthandEntry",
+ "type": "object",
+ "properties": [
+ { "name": "name", "type": "string", "description": "Shorthand name." },
+ { "name": "value", "type": "string", "description": "Shorthand value." },
+ { "name": "important", "type": "boolean", "optional": true, "description": "Whether the property has \"!important\" annotation (implies <code>false</code> if absent)." }
+ ]
+ },
+ {
+ "id": "CSSComputedStyleProperty",
+ "type": "object",
+ "properties": [
+ { "name": "name", "type": "string", "description": "Computed style property name." },
+ { "name": "value", "type": "string", "description": "Computed style property value." }
+ ]
+ },
+ {
+ "id": "CSSStyle",
+ "type": "object",
+ "properties": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId", "optional": true, "description": "The css style sheet identifier (absent for user agent stylesheet and user-specified stylesheet rules) this rule came from." },
+ { "name": "cssProperties", "type": "array", "items": { "$ref": "CSSProperty" }, "description": "CSS properties in the style." },
+ { "name": "shorthandEntries", "type": "array", "items": { "$ref": "ShorthandEntry" }, "description": "Computed values for all shorthands found in the style." },
+ { "name": "cssText", "type": "string", "optional": true, "description": "Style declaration text (if available)." },
+ { "name": "range", "$ref": "SourceRange", "optional": true, "description": "Style declaration range in the enclosing stylesheet (if available)." }
+ ],
+ "description": "CSS style representation."
+ },
+ {
+ "id": "CSSProperty",
+ "type": "object",
+ "properties": [
+ { "name": "name", "type": "string", "description": "The property name." },
+ { "name": "value", "type": "string", "description": "The property value." },
+ { "name": "important", "type": "boolean", "optional": true, "description": "Whether the property has \"!important\" annotation (implies <code>false</code> if absent)." },
+ { "name": "implicit", "type": "boolean", "optional": true, "description": "Whether the property is implicit (implies <code>false</code> if absent)." },
+ { "name": "text", "type": "string", "optional": true, "description": "The full property text as specified in the style." },
+ { "name": "parsedOk", "type": "boolean", "optional": true, "description": "Whether the property is understood by the browser (implies <code>true</code> if absent)." },
+ { "name": "disabled", "type": "boolean", "optional": true, "description": "Whether the property is disabled by the user (present for source-based properties only)." },
+ { "name": "range", "$ref": "SourceRange", "optional": true, "description": "The entire property range in the enclosing style declaration (if available)." }
+ ],
+ "description": "CSS property declaration data."
+ },
+ {
+ "id": "CSSMedia",
+ "type": "object",
+ "properties": [
+ { "name": "text", "type": "string", "description": "Media query text." },
+ { "name": "source", "type": "string", "enum": ["mediaRule", "importRule", "linkedSheet", "inlineSheet"], "description": "Source of the media query: \"mediaRule\" if specified by a @media rule, \"importRule\" if specified by an @import rule, \"linkedSheet\" if specified by a \"media\" attribute in a linked stylesheet's LINK tag, \"inlineSheet\" if specified by a \"media\" attribute in an inline stylesheet's STYLE tag." },
+ { "name": "sourceURL", "type": "string", "optional": true, "description": "URL of the document containing the media query description." },
+ { "name": "range", "$ref": "SourceRange", "optional": true, "description": "The associated rule (@media or @import) header range in the enclosing stylesheet (if available)." },
+ { "name": "styleSheetId", "$ref": "StyleSheetId", "optional": true, "description": "Identifier of the stylesheet containing this object (if exists)." },
+ { "name": "mediaList", "type": "array", "items": { "$ref": "MediaQuery" }, "optional": true, "hidden": true, "description": "Array of media queries." }
+ ],
+ "description": "CSS media rule descriptor."
+ },
+ {
+ "id": "MediaQuery",
+ "type": "object",
+ "properties": [
+ { "name": "expressions", "type": "array", "items": { "$ref": "MediaQueryExpression" }, "description": "Array of media query expressions." },
+ { "name": "active", "type": "boolean", "description": "Whether the media query condition is satisfied." }
+ ],
+ "description": "Media query descriptor.",
+ "hidden": true
+ },
+ {
+ "id": "MediaQueryExpression",
+ "type": "object",
+ "properties": [
+ { "name": "value", "type": "number", "description": "Media query expression value."},
+ { "name": "unit", "type": "string", "description": "Media query expression units."},
+ { "name": "feature", "type": "string", "description": "Media query expression feature."},
+ { "name": "valueRange", "$ref": "SourceRange", "optional": true, "description": "The associated range of the value text in the enclosing stylesheet (if available)." },
+ { "name": "computedLength", "type": "number", "optional": true, "description": "Computed length of media query expression (if applicable)."}
+ ],
+ "description": "Media query expression descriptor.",
+ "hidden": true
+ },
+ {
+ "id": "PlatformFontUsage",
+ "type": "object",
+ "properties": [
+ { "name": "familyName", "type": "string", "description": "Font's family name reported by platform."},
+ { "name": "isCustomFont", "type": "boolean", "description": "Indicates if the font was downloaded or resolved locally."},
+ { "name": "glyphCount", "type": "number", "description": "Amount of glyphs that were rendered with this font."}
+ ],
+ "description": "Information about amount of glyphs that were rendered with given font.",
+ "hidden": true
+ },
+ {
+ "id": "CSSKeyframesRule",
+ "type": "object",
+ "properties": [
+ { "name": "animationName", "$ref": "Value", "description": "Animation name." },
+ { "name": "keyframes", "type": "array", "items": { "$ref": "CSSKeyframeRule" }, "description": "List of keyframes." }
+ ],
+ "description": "CSS keyframes rule representation."
+ },
+ {
+ "id": "CSSKeyframeRule",
+ "type": "object",
+ "properties": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId", "optional": true, "description": "The css style sheet identifier (absent for user agent stylesheet and user-specified stylesheet rules) this rule came from." },
+ { "name": "origin", "$ref": "StyleSheetOrigin", "description": "Parent stylesheet's origin."},
+ { "name": "keyText", "$ref": "Value", "description": "Associated key text." },
+ { "name": "style", "$ref": "CSSStyle", "description": "Associated style declaration." }
+ ],
+ "description": "CSS keyframe rule representation."
+ },
+ {
+ "id": "StyleDeclarationEdit",
+ "type": "object",
+ "properties": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId", "description": "The css style sheet identifier." },
+ { "name": "range", "$ref": "SourceRange", "description": "The range of the style text in the enclosing stylesheet." },
+ { "name": "text", "type": "string", "description": "New style text."}
+ ],
+ "description": "A descriptor of operation to mutate style declaration text."
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "async": true,
+ "description": "Enables the CSS agent for the given page. Clients should not assume that the CSS agent has been enabled until the result of this command is received."
+ },
+ {
+ "name": "disable",
+ "description": "Disables the CSS agent for the given page."
+ },
+ {
+ "name": "getMatchedStylesForNode",
+ "parameters": [
+ { "name": "nodeId", "$ref": "DOM.NodeId" }
+ ],
+ "returns": [
+ { "name": "inlineStyle", "$ref": "CSSStyle", "optional": true, "description": "Inline style for the specified DOM node." },
+ { "name": "attributesStyle", "$ref": "CSSStyle", "optional": true, "description": "Attribute-defined element style (e.g. resulting from \"width=20 height=100%\")."},
+ { "name": "matchedCSSRules", "type": "array", "items": { "$ref": "RuleMatch" }, "optional": true, "description": "CSS rules matching this node, from all applicable stylesheets." },
+ { "name": "pseudoElements", "type": "array", "items": { "$ref": "PseudoElementMatches" }, "optional": true, "description": "Pseudo style matches for this node." },
+ { "name": "inherited", "type": "array", "items": { "$ref": "InheritedStyleEntry" }, "optional": true, "description": "A chain of inherited styles (from the immediate node parent up to the DOM tree root)." },
+ { "name": "cssKeyframesRules", "type": "array", "items": { "$ref": "CSSKeyframesRule" }, "optional": true, "description": "A list of CSS keyframed animations matching this node." }
+ ],
+ "description": "Returns requested styles for a DOM node identified by <code>nodeId</code>."
+ },
+ {
+ "name": "getInlineStylesForNode",
+ "parameters": [
+ { "name": "nodeId", "$ref": "DOM.NodeId" }
+ ],
+ "returns": [
+ { "name": "inlineStyle", "$ref": "CSSStyle", "optional": true, "description": "Inline style for the specified DOM node." },
+ { "name": "attributesStyle", "$ref": "CSSStyle", "optional": true, "description": "Attribute-defined element style (e.g. resulting from \"width=20 height=100%\")."}
+ ],
+ "description": "Returns the styles defined inline (explicitly in the \"style\" attribute and implicitly, using DOM attributes) for a DOM node identified by <code>nodeId</code>."
+ },
+ {
+ "name": "getComputedStyleForNode",
+ "parameters": [
+ { "name": "nodeId", "$ref": "DOM.NodeId" }
+ ],
+ "returns": [
+ { "name": "computedStyle", "type": "array", "items": { "$ref": "CSSComputedStyleProperty" }, "description": "Computed style for the specified DOM node." }
+ ],
+ "description": "Returns the computed style for a DOM node identified by <code>nodeId</code>."
+ },
+ {
+ "name": "getPlatformFontsForNode",
+ "parameters": [
+ { "name": "nodeId", "$ref": "DOM.NodeId" }
+ ],
+ "returns": [
+ { "name": "fonts", "type": "array", "items": { "$ref": "PlatformFontUsage" }, "description": "Usage statistics for every employed platform font." }
+ ],
+ "description": "Requests information about platform fonts which we used to render child TextNodes in the given node.",
+ "hidden": true
+ },
+ {
+ "name": "getStyleSheetText",
+ "parameters": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId" }
+ ],
+ "returns": [
+ { "name": "text", "type": "string", "description": "The stylesheet text." }
+ ],
+ "description": "Returns the current textual content and the URL for a stylesheet."
+ },
+ {
+ "name": "setStyleSheetText",
+ "parameters": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId" },
+ { "name": "text", "type": "string" }
+ ],
+ "returns": [
+ { "name": "sourceMapURL", "type": "string", "optional": true, "description": "URL of source map associated with script (if any)." }
+ ],
+ "description": "Sets the new stylesheet text."
+ },
+ {
+ "name": "setRuleSelector",
+ "parameters": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId" },
+ { "name": "range", "$ref": "SourceRange" },
+ { "name": "selector", "type": "string" }
+ ],
+ "returns": [
+ { "name": "selectorList", "$ref": "SelectorList", "description": "The resulting selector list after modification." }
+ ],
+ "description": "Modifies the rule selector."
+ },
+ {
+ "name": "setKeyframeKey",
+ "parameters": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId" },
+ { "name": "range", "$ref": "SourceRange" },
+ { "name": "keyText", "type": "string" }
+ ],
+ "returns": [
+ { "name": "keyText", "$ref": "Value", "description": "The resulting key text after modification." }
+ ],
+ "description": "Modifies the keyframe rule key text."
+ },
+ {
+ "name": "setStyleTexts",
+ "parameters": [
+ { "name": "edits", "type": "array", "items": { "$ref": "StyleDeclarationEdit" }}
+ ],
+ "returns": [
+ { "name": "styles", "type": "array", "items": { "$ref": "CSSStyle" }, "description": "The resulting styles after modification." }
+ ],
+ "description": "Applies specified style edits one after another in the given order."
+ },
+ {
+ "name": "setMediaText",
+ "parameters": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId" },
+ { "name": "range", "$ref": "SourceRange" },
+ { "name": "text", "type": "string" }
+ ],
+ "returns": [
+ { "name": "media", "$ref": "CSSMedia", "description": "The resulting CSS media rule after modification." }
+ ],
+ "description": "Modifies the rule selector."
+ },
+ {
+ "name": "createStyleSheet",
+ "parameters": [
+ { "name": "frameId", "$ref": "Page.FrameId", "description": "Identifier of the frame where \"via-inspector\" stylesheet should be created."}
+ ],
+ "returns": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId", "description": "Identifier of the created \"via-inspector\" stylesheet." }
+ ],
+ "description": "Creates a new special \"via-inspector\" stylesheet in the frame with given <code>frameId</code>."
+ },
+ {
+ "name": "addRule",
+ "parameters": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId", "description": "The css style sheet identifier where a new rule should be inserted." },
+ { "name": "ruleText", "type": "string", "description": "The text of a new rule." },
+ { "name": "location", "$ref": "SourceRange", "description": "Text position of a new rule in the target style sheet." }
+ ],
+ "returns": [
+ { "name": "rule", "$ref": "CSSRule", "description": "The newly created rule." }
+ ],
+ "description": "Inserts a new rule with the given <code>ruleText</code> in a stylesheet with given <code>styleSheetId</code>, at the position specified by <code>location</code>."
+ },
+ {
+ "name": "forcePseudoState",
+ "parameters": [
+ { "name": "nodeId", "$ref": "DOM.NodeId", "description": "The element id for which to force the pseudo state." },
+ { "name": "forcedPseudoClasses", "type": "array", "items": { "type": "string", "enum": ["active", "focus", "hover", "visited"] }, "description": "Element pseudo classes to force when computing the element's style." }
+ ],
+ "description": "Ensures that the given node will have specified pseudo-classes whenever its style is computed by the browser."
+ },
+ {
+ "name": "getMediaQueries",
+ "returns": [
+ { "name": "medias", "type": "array", "items": { "$ref": "CSSMedia" } }
+ ],
+ "description": "Returns all media queries parsed by the rendering engine.",
+ "hidden": true
+ },
+ {
+ "name": "setEffectivePropertyValueForNode",
+ "parameters": [
+ { "name": "nodeId", "$ref": "DOM.NodeId", "description": "The element id for which to set property." },
+ { "name": "propertyName", "type": "string"},
+ { "name": "value", "type": "string"}
+ ],
+ "description": "Find a rule with the given active property for the given node and set the new value for this property",
+ "hidden": true
+ },
+ {
+ "name": "getBackgroundColors",
+ "parameters": [
+ { "name": "nodeId", "$ref": "DOM.NodeId", "description": "Id of the node to get background colors for." }
+ ],
+ "returns": [
+ { "name": "backgroundColors", "type": "array", "items": { "type": "string" }, "description": "The range of background colors behind this element, if it contains any visible text. If no visible text is present, this will be undefined. In the case of a flat background color, this will consist of simply that color. In the case of a gradient, this will consist of each of the color stops. For anything more complicated, this will be an empty array. Images will be ignored (as if the image had failed to load).", "optional": true }
+ ],
+ "hidden": true
+ }
+ ],
+ "events": [
+ {
+ "name": "mediaQueryResultChanged",
+ "description": "Fires whenever a MediaQuery result changes (for example, after a browser window has been resized.) The current implementation considers only viewport-dependent media features."
+ },
+ {
+ "name": "styleSheetChanged",
+ "parameters": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId" }
+ ],
+ "description": "Fired whenever a stylesheet is changed as a result of the client operation."
+ },
+ {
+ "name": "styleSheetAdded",
+ "parameters": [
+ { "name": "header", "$ref": "CSSStyleSheetHeader", "description": "Added stylesheet metainfo." }
+ ],
+ "description": "Fired whenever an active document stylesheet is added."
+ },
+ {
+ "name": "styleSheetRemoved",
+ "parameters": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId", "description": "Identifier of the removed stylesheet." }
+ ],
+ "description": "Fired whenever an active document stylesheet is removed."
+ },
+ {
+ "name": "layoutEditorChange",
+ "parameters": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId", "description": "Identifier of the stylesheet where the modification occurred." },
+ { "name": "changeRange", "$ref": "SourceRange", "description": "Range where the modification occurred." }
+ ]
+ }
+ ]
+ },
+ {
+ "domain": "IO",
+ "description": "Input/Output operations for streams produced by DevTools.",
+ "hidden": true,
+ "types": [
+ {
+ "id": "StreamHandle",
+ "type": "string"
+ }
+ ],
+ "commands": [
+ {
+ "name": "read",
+ "description": "Read a chunk of the stream",
+ "async": true,
+ "parameters": [
+ { "name": "handle", "$ref": "StreamHandle", "description": "Handle of the stream to read." },
+ { "name": "offset", "type": "integer", "optional": true, "description": "Seek to the specified offset before reading (if not specificed, proceed with offset following the last read)." },
+ { "name": "size", "type": "integer", "optional": true, "description": "Maximum number of bytes to read (left upon the agent discretion if not specified)." }
+ ],
+ "returns": [
+ { "name": "data", "type": "string", "description": "Data that were read." },
+ { "name": "eof", "type": "boolean", "description": "Set if the end-of-file condition occured while reading." }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "close",
+ "description": "Close the stream, discard any temporary backing storage.",
+ "parameters": [
+ { "name": "handle", "$ref": "StreamHandle", "description": "Handle of the stream to close." }
+ ],
+ "handlers": ["browser"]
+ }
+ ]
+ },
+ {
+ "domain": "Debugger",
+ "description": "Debugger domain exposes JavaScript debugging capabilities. It allows setting and removing breakpoints, stepping through execution, exploring stack traces, etc.",
+ "types": [
+ {
+ "id": "BreakpointId",
+ "type": "string",
+ "description": "Breakpoint identifier."
+ },
+ {
+ "id": "CallFrameId",
+ "type": "string",
+ "description": "Call frame identifier."
+ },
+ {
+ "id": "Location",
+ "type": "object",
+ "properties": [
+ { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Script identifier as reported in the <code>Debugger.scriptParsed</code>." },
+ { "name": "lineNumber", "type": "integer", "description": "Line number in the script (0-based)." },
+ { "name": "columnNumber", "type": "integer", "optional": true, "description": "Column number in the script (0-based)." }
+ ],
+ "description": "Location in the source code."
+ },
+ {
+ "id": "ScriptPosition",
+ "hidden": true,
+ "type": "object",
+ "properties": [
+ { "name": "line", "type": "integer" },
+ { "name": "column", "type": "integer" }
+ ],
+ "description": "Location in the source code."
+ },
+ {
+ "id": "FunctionDetails",
+ "hidden": true,
+ "type": "object",
+ "properties": [
+ { "name": "location", "$ref": "Location", "optional": true, "description": "Location of the function, none for native functions." },
+ { "name": "functionName", "type": "string", "description": "Name of the function." },
+ { "name": "isGenerator", "type": "boolean", "description": "Whether this is a generator function." },
+ { "name": "scopeChain", "type": "array", "optional": true, "items": { "$ref": "Scope" }, "description": "Scope chain for this closure." }
+ ],
+ "description": "Information about the function."
+ },
+ {
+ "id": "GeneratorObjectDetails",
+ "hidden": true,
+ "type": "object",
+ "properties": [
+ { "name": "function", "$ref": "Runtime.RemoteObject", "description": "Generator function." },
+ { "name": "functionName", "type": "string", "description": "Name of the generator function." },
+ { "name": "status", "type": "string", "enum": ["running", "suspended", "closed"], "description": "Current generator object status." },
+ { "name": "location", "$ref": "Location", "optional": true, "description": "If suspended, location where generator function was suspended (e.g. location of the last 'yield'). Otherwise, location of the generator function." }
+ ],
+ "description": "Information about the generator object."
+ },
+ {
+ "id": "CollectionEntry",
+ "hidden": true,
+ "type": "object",
+ "properties": [
+ { "name": "key", "$ref": "Runtime.RemoteObject", "optional": true, "description": "Entry key of a map-like collection, otherwise not provided." },
+ { "name": "value", "$ref": "Runtime.RemoteObject", "description": "Entry value." }
+ ],
+ "description": "Collection entry."
+ },
+ {
+ "id": "CallFrame",
+ "type": "object",
+ "properties": [
+ { "name": "callFrameId", "$ref": "CallFrameId", "description": "Call frame identifier. This identifier is only valid while the virtual machine is paused." },
+ { "name": "functionName", "type": "string", "description": "Name of the JavaScript function called on this call frame." },
+ { "name": "functionLocation", "$ref": "Location", "optional": true, "hidden": true, "description": "Location in the source code." },
+ { "name": "location", "$ref": "Location", "description": "Location in the source code." },
+ { "name": "scopeChain", "type": "array", "items": { "$ref": "Scope" }, "description": "Scope chain for this call frame." },
+ { "name": "this", "$ref": "Runtime.RemoteObject", "description": "<code>this</code> object for this call frame." },
+ { "name": "returnValue", "$ref": "Runtime.RemoteObject", "optional": true, "hidden": true, "description": "The value being returned, if the function is at return point." }
+ ],
+ "description": "JavaScript call frame. Array of call frames form the call stack."
+ },
+ {
+ "id": "Scope",
+ "type": "object",
+ "properties": [
+ { "name": "type", "type": "string", "enum": ["global", "local", "with", "closure", "catch", "block", "script"], "description": "Scope type." },
+ { "name": "object", "$ref": "Runtime.RemoteObject", "description": "Object representing the scope. For <code>global</code> and <code>with</code> scopes it represents the actual object; for the rest of the scopes, it is artificial transient object enumerating scope variables as its properties." },
+ { "name": "name", "type": "string", "optional": true, "hidden": true },
+ { "name": "startLocation", "$ref": "Location", "optional": true, "hidden": true, "description": "Location in the source code where scope starts" },
+ { "name": "endLocation", "$ref": "Location", "optional": true, "hidden": true, "description": "Location in the source code where scope ends" }
+ ],
+ "description": "Scope description."
+ },
+ {
+ "id": "SetScriptSourceError",
+ "type": "object",
+ "properties": [
+ { "name": "message", "type": "string", "description": "Compiler error message" },
+ { "name": "lineNumber", "type": "integer", "description": "Compile error line number (1-based)" },
+ { "name": "columnNumber", "type": "integer", "description": "Compile error column number (1-based)" }
+ ],
+ "description": "Error data for setScriptSource command. Contains uncompilable script source error.",
+ "hidden": true
+ },
+ {
+ "id": "SearchMatch",
+ "type": "object",
+ "description": "Search match for resource.",
+ "properties": [
+ { "name": "lineNumber", "type": "number", "description": "Line number in resource content." },
+ { "name": "lineContent", "type": "string", "description": "Line with match content." }
+ ],
+ "hidden": true
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables debugger for the given page. Clients should not assume that the debugging has been enabled until the result for this command is received."
+ },
+ {
+ "name": "disable",
+ "description": "Disables debugger for given page."
+ },
+ {
+ "name": "setBreakpointsActive",
+ "parameters": [
+ { "name": "active", "type": "boolean", "description": "New value for breakpoints active state." }
+ ],
+ "description": "Activates / deactivates all breakpoints on the page."
+ },
+ {
+ "name": "setSkipAllPauses",
+ "hidden": true,
+ "parameters": [
+ { "name": "skipped", "type": "boolean", "description": "New value for skip pauses state." }
+ ],
+ "description": "Makes page not interrupt on any pauses (breakpoint, exception, dom exception etc)."
+ },
+ {
+ "name": "setBreakpointByUrl",
+ "parameters": [
+ { "name": "lineNumber", "type": "integer", "description": "Line number to set breakpoint at." },
+ { "name": "url", "type": "string", "optional": true, "description": "URL of the resources to set breakpoint on." },
+ { "name": "urlRegex", "type": "string", "optional": true, "description": "Regex pattern for the URLs of the resources to set breakpoints on. Either <code>url</code> or <code>urlRegex</code> must be specified." },
+ { "name": "columnNumber", "type": "integer", "optional": true, "description": "Offset in the line to set breakpoint at." },
+ { "name": "condition", "type": "string", "optional": true, "description": "Expression to use as a breakpoint condition. When specified, debugger will only stop on the breakpoint if this expression evaluates to true." }
+ ],
+ "returns": [
+ { "name": "breakpointId", "$ref": "BreakpointId", "description": "Id of the created breakpoint for further reference." },
+ { "name": "locations", "type": "array", "items": { "$ref": "Location" }, "description": "List of the locations this breakpoint resolved into upon addition." }
+ ],
+ "description": "Sets JavaScript breakpoint at given location specified either by URL or URL regex. Once this command is issued, all existing parsed scripts will have breakpoints resolved and returned in <code>locations</code> property. Further matching script parsing will result in subsequent <code>breakpointResolved</code> events issued. This logical breakpoint will survive page reloads."
+ },
+ {
+ "name": "setBreakpoint",
+ "parameters": [
+ { "name": "location", "$ref": "Location", "description": "Location to set breakpoint in." },
+ { "name": "condition", "type": "string", "optional": true, "description": "Expression to use as a breakpoint condition. When specified, debugger will only stop on the breakpoint if this expression evaluates to true." }
+ ],
+ "returns": [
+ { "name": "breakpointId", "$ref": "BreakpointId", "description": "Id of the created breakpoint for further reference." },
+ { "name": "actualLocation", "$ref": "Location", "description": "Location this breakpoint resolved into." }
+ ],
+ "description": "Sets JavaScript breakpoint at a given location."
+ },
+ {
+ "name": "removeBreakpoint",
+ "parameters": [
+ { "name": "breakpointId", "$ref": "BreakpointId" }
+ ],
+ "description": "Removes JavaScript breakpoint."
+ },
+ {
+ "name": "continueToLocation",
+ "parameters": [
+ { "name": "location", "$ref": "Location", "description": "Location to continue to." },
+ { "name": "interstatementLocation", "type": "boolean", "optional": true, "hidden": true, "description": "Allows breakpoints at the intemediate positions inside statements." }
+ ],
+ "description": "Continues execution until specific location is reached."
+ },
+ {
+ "name": "stepOver",
+ "description": "Steps over the statement."
+ },
+ {
+ "name": "stepInto",
+ "description": "Steps into the function call."
+ },
+ {
+ "name": "stepOut",
+ "description": "Steps out of the function call."
+ },
+ {
+ "name": "pause",
+ "description": "Stops on the next JavaScript statement."
+ },
+ {
+ "name": "resume",
+ "description": "Resumes JavaScript execution."
+ },
+ {
+ "name": "searchInContent",
+ "parameters": [
+ { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Id of the script to search in." },
+ { "name": "query", "type": "string", "description": "String to search for." },
+ { "name": "caseSensitive", "type": "boolean", "optional": true, "description": "If true, search is case sensitive." },
+ { "name": "isRegex", "type": "boolean", "optional": true, "description": "If true, treats string parameter as regex." }
+ ],
+ "returns": [
+ { "name": "result", "type": "array", "items": { "$ref": "SearchMatch" }, "description": "List of search matches." }
+ ],
+ "description": "Searches for given string in script content."
+ },
+ {
+ "name": "canSetScriptSource",
+ "returns": [
+ { "name": "result", "type": "boolean", "description": "True if <code>setScriptSource</code> is supported." }
+ ],
+ "description": "Always returns true."
+ },
+ {
+ "name": "setScriptSource",
+ "parameters": [
+ { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Id of the script to edit." },
+ { "name": "scriptSource", "type": "string", "description": "New content of the script." },
+ { "name": "preview", "type": "boolean", "optional": true, "description": " If true the change will not actually be applied. Preview mode may be used to get result description without actually modifying the code.", "hidden": true }
+ ],
+ "returns": [
+ { "name": "callFrames", "type": "array", "optional": true, "items": { "$ref": "CallFrame" }, "description": "New stack trace in case editing has happened while VM was stopped." },
+ { "name": "stackChanged", "type": "boolean", "optional": true, "description": "Whether current call stack was modified after applying the changes.", "hidden": true },
+ { "name": "asyncStackTrace", "$ref": "Runtime.StackTrace", "optional": true, "description": "Async stack trace, if any.", "hidden": true },
+ { "name": "compileError", "optional": true, "$ref": "SetScriptSourceError", "description": "Error data if any." }
+ ],
+ "description": "Edits JavaScript source live."
+ },
+ {
+ "name": "restartFrame",
+ "parameters": [
+ { "name": "callFrameId", "$ref": "CallFrameId", "description": "Call frame identifier to evaluate on." }
+ ],
+ "returns": [
+ { "name": "callFrames", "type": "array", "items": { "$ref": "CallFrame" }, "description": "New stack trace." },
+ { "name": "asyncStackTrace", "$ref": "Runtime.StackTrace", "optional": true, "description": "Async stack trace, if any." }
+ ],
+ "hidden": true,
+ "description": "Restarts particular call frame from the beginning."
+ },
+ {
+ "name": "getScriptSource",
+ "parameters": [
+ { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Id of the script to get source for." }
+ ],
+ "returns": [
+ { "name": "scriptSource", "type": "string", "description": "Script source." }
+ ],
+ "description": "Returns source for the script with given id."
+ },
+ {
+ "name": "getFunctionDetails",
+ "hidden": true,
+ "parameters": [
+ { "name": "functionId", "$ref": "Runtime.RemoteObjectId", "description": "Id of the function to get details for." }
+ ],
+ "returns": [
+ { "name": "details", "$ref": "FunctionDetails", "description": "Information about the function." }
+ ],
+ "description": "Returns detailed information on given function."
+ },
+ {
+ "name": "getGeneratorObjectDetails",
+ "hidden": true,
+ "parameters": [
+ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "Id of the generator object to get details for." }
+ ],
+ "returns": [
+ { "name": "details", "$ref": "GeneratorObjectDetails", "description": "Information about the generator object." }
+ ],
+ "description": "Returns detailed information on given generator object."
+ },
+ {
+ "name": "getCollectionEntries",
+ "hidden": true,
+ "parameters": [
+ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "Id of the collection to get entries for." }
+ ],
+ "returns": [
+ { "name": "entries", "type": "array", "items": { "$ref": "CollectionEntry" }, "description": "Array of collection entries." }
+ ],
+ "description": "Returns entries of given collection."
+ },
+ {
+ "name": "setPauseOnExceptions",
+ "parameters": [
+ { "name": "state", "type": "string", "enum": ["none", "uncaught", "all"], "description": "Pause on exceptions mode." }
+ ],
+ "description": "Defines pause on exceptions state. Can be set to stop on all exceptions, uncaught exceptions or no exceptions. Initial pause on exceptions state is <code>none</code>."
+ },
+ {
+ "name": "evaluateOnCallFrame",
+ "parameters": [
+ { "name": "callFrameId", "$ref": "CallFrameId", "description": "Call frame identifier to evaluate on." },
+ { "name": "expression", "type": "string", "description": "Expression to evaluate." },
+ { "name": "objectGroup", "type": "string", "optional": true, "description": "String object group name to put result into (allows rapid releasing resulting object handles using <code>releaseObjectGroup</code>)." },
+ { "name": "includeCommandLineAPI", "type": "boolean", "optional": true, "description": "Specifies whether command line API should be available to the evaluated expression, defaults to false.", "hidden": true },
+ { "name": "doNotPauseOnExceptionsAndMuteConsole", "type": "boolean", "optional": true, "description": "Specifies whether evaluation should stop on exceptions and mute console. Overrides setPauseOnException state.", "hidden": true },
+ { "name": "returnByValue", "type": "boolean", "optional": true, "description": "Whether the result is expected to be a JSON object that should be sent by value." },
+ { "name": "generatePreview", "type": "boolean", "optional": true, "hidden": true, "description": "Whether preview should be generated for the result." }
+ ],
+ "returns": [
+ { "name": "result", "$ref": "Runtime.RemoteObject", "description": "Object wrapper for the evaluation result." },
+ { "name": "wasThrown", "type": "boolean", "optional": true, "description": "True if the result was thrown during the evaluation." },
+ { "name": "exceptionDetails", "$ref": "Runtime.ExceptionDetails", "optional": true, "hidden": true, "description": "Exception details."}
+ ],
+ "description": "Evaluates expression on a given call frame."
+ },
+ {
+ "name": "setVariableValue",
+ "parameters": [
+ { "name": "scopeNumber", "type": "integer", "description": "0-based number of scope as was listed in scope chain. Only 'local', 'closure' and 'catch' scope types are allowed. Other scopes could be manipulated manually." },
+ { "name": "variableName", "type": "string", "description": "Variable name." },
+ { "name": "newValue", "$ref": "Runtime.CallArgument", "description": "New variable value." },
+ { "name": "callFrameId", "$ref": "CallFrameId", "description": "Id of callframe that holds variable." }
+ ],
+ "hidden": true,
+ "description": "Changes value of variable in a callframe. Object-based scopes are not supported and must be mutated manually."
+ },
+ {
+ "name": "getBacktrace",
+ "returns": [
+ { "name": "callFrames", "type": "array", "items": { "$ref": "CallFrame" }, "description": "Call stack the virtual machine stopped on." },
+ { "name": "asyncStackTrace", "$ref": "Runtime.StackTrace", "optional": true, "description": "Async stack trace, if any." }
+ ],
+ "hidden": true,
+ "description": "Returns call stack including variables changed since VM was paused. VM must be paused."
+ },
+ {
+ "name": "setAsyncCallStackDepth",
+ "parameters": [
+ { "name": "maxDepth", "type": "integer", "description": "Maximum depth of async call stacks. Setting to <code>0</code> will effectively disable collecting async call stacks (default)." }
+ ],
+ "hidden": true,
+ "description": "Enables or disables async call stacks tracking."
+ },
+ {
+ "name": "setBlackboxPatterns",
+ "parameters": [
+ { "name": "patterns", "type": "array", "items": { "type": "string" }, "description": "Array of regexps that will be used to check script url for blackbox state." }
+ ],
+ "hidden": true,
+ "description": "Replace previous blackbox patterns with passed ones. Forces backend to skip stepping/pausing in scripts with url matching one of the patterns. VM will try to leave blackboxed script by performing 'step in' several times, finally resorting to 'step out' if unsuccessful."
+ },
+ {
+ "name": "setBlackboxedRanges",
+ "parameters": [
+ { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Id of the script." },
+ { "name": "positions", "type": "array", "items": { "$ref": "ScriptPosition" } }
+ ],
+ "hidden": true,
+ "description": "Makes backend skip steps in the script in blackboxed ranges. VM will try leave blacklisted scripts by performing 'step in' several times, finally resorting to 'step out' if unsuccessful. Positions array contains positions where blackbox state is changed. First interval isn't blackboxed. Array should be sorted."
+ }
+ ],
+ "events": [
+ {
+ "name": "scriptParsed",
+ "parameters": [
+ { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Identifier of the script parsed." },
+ { "name": "url", "type": "string", "description": "URL or name of the script parsed (if any)." },
+ { "name": "startLine", "type": "integer", "description": "Line offset of the script within the resource with given URL (for script tags)." },
+ { "name": "startColumn", "type": "integer", "description": "Column offset of the script within the resource with given URL." },
+ { "name": "endLine", "type": "integer", "description": "Last line of the script." },
+ { "name": "endColumn", "type": "integer", "description": "Length of the last line of the script." },
+ { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "description": "Specifies script creation context.", "hidden": true },
+ { "name": "hash", "type": "string", "hidden": true, "description": "Content hash of the script."},
+ { "name": "isContentScript", "type": "boolean", "optional": true, "description": "Determines whether this script is a user extension script." },
+ { "name": "isInternalScript", "type": "boolean", "optional": true, "description": "Determines whether this script is an internal script.", "hidden": true },
+ { "name": "isLiveEdit", "type": "boolean", "optional": true, "description": "True, if this script is generated as a result of the live edit operation.", "hidden": true },
+ { "name": "sourceMapURL", "type": "string", "optional": true, "description": "URL of source map associated with script (if any)." },
+ { "name": "hasSourceURL", "type": "boolean", "optional": true, "description": "True, if this script has sourceURL.", "hidden": true },
+ { "name": "deprecatedCommentWasUsed", "type": "boolean", "optional": true, "hidden": true, "description": "True, if '//@ sourceURL' or '//@ sourceMappingURL' was used."}
+ ],
+ "description": "Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger."
+ },
+ {
+ "name": "scriptFailedToParse",
+ "parameters": [
+ { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Identifier of the script parsed." },
+ { "name": "url", "type": "string", "description": "URL or name of the script parsed (if any)." },
+ { "name": "startLine", "type": "integer", "description": "Line offset of the script within the resource with given URL (for script tags)." },
+ { "name": "startColumn", "type": "integer", "description": "Column offset of the script within the resource with given URL." },
+ { "name": "endLine", "type": "integer", "description": "Last line of the script." },
+ { "name": "endColumn", "type": "integer", "description": "Length of the last line of the script." },
+ { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "description": "Specifies script creation context.", "hidden": true },
+ { "name": "hash", "type": "string", "hidden": true, "description": "Content hash of the script."},
+ { "name": "isContentScript", "type": "boolean", "optional": true, "description": "Determines whether this script is a user extension script." },
+ { "name": "isInternalScript", "type": "boolean", "optional": true, "description": "Determines whether this script is an internal script.", "hidden": true },
+ { "name": "sourceMapURL", "type": "string", "optional": true, "description": "URL of source map associated with script (if any)." },
+ { "name": "hasSourceURL", "type": "boolean", "optional": true, "description": "True, if this script has sourceURL.", "hidden": true },
+ { "name": "deprecatedCommentWasUsed", "type": "boolean", "optional": true, "hidden": true, "description": "True, if '//@ sourceURL' or '//@ sourceMappingURL' was used."}
+ ],
+ "description": "Fired when virtual machine fails to parse the script."
+ },
+ {
+ "name": "breakpointResolved",
+ "parameters": [
+ { "name": "breakpointId", "$ref": "BreakpointId", "description": "Breakpoint unique identifier." },
+ { "name": "location", "$ref": "Location", "description": "Actual breakpoint location." }
+ ],
+ "description": "Fired when breakpoint is resolved to an actual script and location."
+ },
+ {
+ "name": "paused",
+ "parameters": [
+ { "name": "callFrames", "type": "array", "items": { "$ref": "CallFrame" }, "description": "Call stack the virtual machine stopped on." },
+ { "name": "reason", "type": "string", "enum": [ "XHR", "DOM", "EventListener", "exception", "assert", "CSPViolation", "debugCommand", "promiseRejection", "other" ], "description": "Pause reason." },
+ { "name": "data", "type": "object", "optional": true, "description": "Object containing break-specific auxiliary properties." },
+ { "name": "hitBreakpoints", "type": "array", "optional": true, "items": { "type": "string" }, "description": "Hit breakpoints IDs", "hidden": true },
+ { "name": "asyncStackTrace", "$ref": "Runtime.StackTrace", "optional": true, "description": "Async stack trace, if any.", "hidden": true }
+ ],
+ "description": "Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria."
+ },
+ {
+ "name": "resumed",
+ "description": "Fired when the virtual machine resumed execution."
+ }
+ ]
+ },
+ {
+ "domain": "DOMDebugger",
+ "description": "DOM debugging allows setting breakpoints on particular DOM operations and events. JavaScript execution will stop on these operations as if there was a regular breakpoint set.",
+ "types": [
+ {
+ "id": "DOMBreakpointType",
+ "type": "string",
+ "enum": ["subtree-modified", "attribute-modified", "node-removed"],
+ "description": "DOM breakpoint type."
+ },
+ {
+ "id": "EventListener",
+ "type": "object",
+ "description": "Object event listener.",
+ "properties": [
+ { "name": "type", "type": "string", "description": "<code>EventListener</code>'s type." },
+ { "name": "useCapture", "type": "boolean", "description": "<code>EventListener</code>'s useCapture." },
+ { "name": "passive", "type": "boolean", "description": "<code>EventListener</code>'s passive flag." },
+ { "name": "location", "$ref": "Debugger.Location", "description": "Handler code location." },
+ { "name": "handler", "$ref": "Runtime.RemoteObject", "optional": true, "description": "Event handler function value." },
+ { "name": "originalHandler", "$ref": "Runtime.RemoteObject", "optional": true, "description": "Event original handler function value." }
+ ],
+ "hidden": true
+ }
+ ],
+ "commands": [
+ {
+ "name": "setDOMBreakpoint",
+ "parameters": [
+ { "name": "nodeId", "$ref": "DOM.NodeId", "description": "Identifier of the node to set breakpoint on." },
+ { "name": "type", "$ref": "DOMBreakpointType", "description": "Type of the operation to stop upon." }
+ ],
+ "description": "Sets breakpoint on particular operation with DOM."
+ },
+ {
+ "name": "removeDOMBreakpoint",
+ "parameters": [
+ { "name": "nodeId", "$ref": "DOM.NodeId", "description": "Identifier of the node to remove breakpoint from." },
+ { "name": "type", "$ref": "DOMBreakpointType", "description": "Type of the breakpoint to remove." }
+ ],
+ "description": "Removes DOM breakpoint that was set using <code>setDOMBreakpoint</code>."
+ },
+ {
+ "name": "setEventListenerBreakpoint",
+ "parameters": [
+ { "name": "eventName", "type": "string", "description": "DOM Event name to stop on (any DOM event will do)." },
+ { "name": "targetName", "type": "string", "optional": true, "description": "EventTarget interface name to stop on. If equal to <code>\"*\"</code> or not provided, will stop on any EventTarget.", "hidden": true }
+ ],
+ "description": "Sets breakpoint on particular DOM event."
+ },
+ {
+ "name": "removeEventListenerBreakpoint",
+ "parameters": [
+ { "name": "eventName", "type": "string", "description": "Event name." },
+ { "name": "targetName", "type": "string", "optional": true, "description": "EventTarget interface name.", "hidden": true }
+ ],
+ "description": "Removes breakpoint on particular DOM event."
+ },
+ {
+ "name": "setInstrumentationBreakpoint",
+ "parameters": [
+ { "name": "eventName", "type": "string", "description": "Instrumentation name to stop on." }
+ ],
+ "description": "Sets breakpoint on particular native event.",
+ "hidden": true
+ },
+ {
+ "name": "removeInstrumentationBreakpoint",
+ "parameters": [
+ { "name": "eventName", "type": "string", "description": "Instrumentation name to stop on." }
+ ],
+ "description": "Removes breakpoint on particular native event.",
+ "hidden": true
+ },
+ {
+ "name": "setXHRBreakpoint",
+ "parameters": [
+ { "name": "url", "type": "string", "description": "Resource URL substring. All XHRs having this substring in the URL will get stopped upon." }
+ ],
+ "description": "Sets breakpoint on XMLHttpRequest."
+ },
+ {
+ "name": "removeXHRBreakpoint",
+ "parameters": [
+ { "name": "url", "type": "string", "description": "Resource URL substring." }
+ ],
+ "description": "Removes breakpoint from XMLHttpRequest."
+ },
+ {
+ "name": "getEventListeners",
+ "hidden": true,
+ "parameters": [
+ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "Identifier of the object to return listeners for." }
+ ],
+ "returns": [
+ { "name": "listeners", "type": "array", "items": { "$ref": "EventListener" }, "description": "Array of relevant listeners." }
+ ],
+ "description": "Returns event listeners of the given object."
+ }
+ ]
+ },
+ {
+ "domain": "Profiler",
+ "hidden": true,
+ "types": [
+ {
+ "id": "CPUProfileNode",
+ "type": "object",
+ "description": "CPU Profile node. Holds callsite information, execution statistics and child nodes.",
+ "properties": [
+ { "name": "functionName", "type": "string", "description": "Function name." },
+ { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Script identifier." },
+ { "name": "url", "type": "string", "description": "URL." },
+ { "name": "lineNumber", "type": "integer", "description": "1-based line number of the function start position." },
+ { "name": "columnNumber", "type": "integer", "description": "1-based column number of the function start position." },
+ { "name": "hitCount", "type": "integer", "description": "Number of samples where this node was on top of the call stack." },
+ { "name": "callUID", "type": "number", "description": "Call UID." },
+ { "name": "children", "type": "array", "items": { "$ref": "CPUProfileNode" }, "description": "Child nodes." },
+ { "name": "deoptReason", "type": "string", "description": "The reason of being not optimized. The function may be deoptimized or marked as don't optimize."},
+ { "name": "id", "type": "integer", "description": "Unique id of the node." },
+ { "name": "positionTicks", "type": "array", "items": { "$ref": "PositionTickInfo" }, "description": "An array of source position ticks." }
+ ]
+ },
+ {
+ "id": "CPUProfile",
+ "type": "object",
+ "description": "Profile.",
+ "properties": [
+ { "name": "head", "$ref": "CPUProfileNode" },
+ { "name": "startTime", "type": "number", "description": "Profiling start time in seconds." },
+ { "name": "endTime", "type": "number", "description": "Profiling end time in seconds." },
+ { "name": "samples", "optional": true, "type": "array", "items": { "type": "integer" }, "description": "Ids of samples top nodes." },
+ { "name": "timestamps", "optional": true, "type": "array", "items": { "type": "number" }, "description": "Timestamps of the samples in microseconds." }
+ ]
+ },
+ {
+ "id": "PositionTickInfo",
+ "type": "object",
+ "description": "Specifies a number of samples attributed to a certain source position.",
+ "properties": [
+ { "name": "line", "type": "integer", "description": "Source line number (1-based)." },
+ { "name": "ticks", "type": "integer", "description": "Number of samples attributed to the source line." }
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable"
+ },
+ {
+ "name": "disable"
+ },
+ {
+ "name": "setSamplingInterval",
+ "parameters": [
+ { "name": "interval", "type": "integer", "description": "New sampling interval in microseconds." }
+ ],
+ "description": "Changes CPU profiler sampling interval. Must be called before CPU profiles recording started."
+ },
+ {
+ "name": "start"
+ },
+ {
+ "name": "stop",
+ "returns": [
+ { "name": "profile", "$ref": "CPUProfile", "description": "Recorded profile." }
+ ]
+ }
+ ],
+ "events": [
+ {
+ "name": "consoleProfileStarted",
+ "parameters": [
+ { "name": "id", "type": "string" },
+ { "name": "location", "$ref": "Debugger.Location", "description": "Location of console.profile()." },
+ { "name": "title", "type": "string", "optional": true, "description": "Profile title passed as argument to console.profile()." }
+
+ ],
+ "description": "Sent when new profile recodring is started using console.profile() call."
+ },
+ {
+ "name": "consoleProfileFinished",
+ "parameters": [
+ { "name": "id", "type": "string" },
+ { "name": "location", "$ref": "Debugger.Location", "description": "Location of console.profileEnd()." },
+ { "name": "profile", "$ref": "CPUProfile" },
+ { "name": "title", "type": "string", "optional": true, "description": "Profile title passed as argunet to console.profile()." }
+ ]
+ }
+ ]
+ },
+ {
+ "domain": "HeapProfiler",
+ "hidden": true,
+ "types": [
+ {
+ "id": "HeapSnapshotObjectId",
+ "type": "string",
+ "description": "Heap snapshot object id."
+ },
+ {
+ "id": "SamplingHeapProfileNode",
+ "type": "object",
+ "description": "Sampling Heap Profile node. Holds callsite information, allocation statistics and child nodes.",
+ "properties": [
+ { "name": "functionName", "type": "string", "description": "Function name." },
+ { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Script identifier." },
+ { "name": "url", "type": "string", "description": "URL." },
+ { "name": "lineNumber", "type": "integer", "description": "1-based line number of the function start position." },
+ { "name": "columnNumber", "type": "integer", "description": "1-based column number of the function start position." },
+ { "name": "selfSize", "type": "number", "description": "Allocations size in bytes for the node excluding children." },
+ { "name": "children", "type": "array", "items": { "$ref": "SamplingHeapProfileNode" }, "description": "Child nodes." }
+ ]
+ },
+ {
+ "id": "SamplingHeapProfile",
+ "type": "object",
+ "description": "Profile.",
+ "properties": [
+ { "name": "head", "$ref": "SamplingHeapProfileNode" }
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable"
+ },
+ {
+ "name": "disable"
+ },
+ {
+ "name": "startTrackingHeapObjects",
+ "parameters": [
+ { "name": "trackAllocations", "type": "boolean", "optional": true }
+ ]
+ },
+ {
+ "name": "stopTrackingHeapObjects",
+ "parameters": [
+ { "name": "reportProgress", "type": "boolean", "optional": true, "description": "If true 'reportHeapSnapshotProgress' events will be generated while snapshot is being taken when the tracking is stopped." }
+ ]
+
+ },
+ {
+ "name": "takeHeapSnapshot",
+ "parameters": [
+ { "name": "reportProgress", "type": "boolean", "optional": true, "description": "If true 'reportHeapSnapshotProgress' events will be generated while snapshot is being taken." }
+ ]
+ },
+ {
+ "name": "collectGarbage"
+ },
+ {
+ "name": "getObjectByHeapObjectId",
+ "parameters": [
+ { "name": "objectId", "$ref": "HeapSnapshotObjectId" },
+ { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." }
+ ],
+ "returns": [
+ { "name": "result", "$ref": "Runtime.RemoteObject", "description": "Evaluation result." }
+ ]
+ },
+ {
+ "name": "addInspectedHeapObject",
+ "parameters": [
+ { "name": "heapObjectId", "$ref": "HeapSnapshotObjectId", "description": "Heap snapshot object id to be accessible by means of $x command line API." }
+ ],
+ "description": "Enables console to refer to the node with given id via $x (see Command Line API for more details $x functions)."
+ },
+ {
+ "name": "getHeapObjectId",
+ "parameters": [
+ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "Identifier of the object to get heap object id for." }
+ ],
+ "returns": [
+ { "name": "heapSnapshotObjectId", "$ref": "HeapSnapshotObjectId", "description": "Id of the heap snapshot object corresponding to the passed remote object id." }
+ ]
+ },
+ {
+ "name": "startSampling",
+ "parameters": [
+ { "name": "samplingInterval", "type": "number", "optional": true, "description": "Average sample interval in bytes. Poisson distribution is used for the intervals. The default value is 32768 bytes." }
+ ]
+ },
+ {
+ "name": "stopSampling",
+ "returns": [
+ { "name": "profile", "$ref": "SamplingHeapProfile", "description": "Recorded sampling heap profile." }
+ ]
+ }
+ ],
+ "events": [
+ {
+ "name": "addHeapSnapshotChunk",
+ "parameters": [
+ { "name": "chunk", "type": "string" }
+ ]
+ },
+ {
+ "name": "resetProfiles"
+ },
+ {
+ "name": "reportHeapSnapshotProgress",
+ "parameters": [
+ { "name": "done", "type": "integer" },
+ { "name": "total", "type": "integer" },
+ { "name": "finished", "type": "boolean", "optional": true }
+ ]
+ },
+ {
+ "name": "lastSeenObjectId",
+ "description": "If heap objects tracking has been started then backend regulary sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event.",
+ "parameters": [
+ { "name": "lastSeenObjectId", "type": "integer" },
+ { "name": "timestamp", "type": "number" }
+ ]
+ },
+ {
+ "name": "heapStatsUpdate",
+ "description": "If heap objects tracking has been started then backend may send update for one or more fragments",
+ "parameters": [
+ { "name": "statsUpdate", "type": "array", "items": { "type": "integer" }, "description": "An array of triplets. Each triplet describes a fragment. The first integer is the fragment index, the second integer is a total count of objects for the fragment, the third integer is a total size of the objects for the fragment."}
+ ]
+ }
+ ]
+ },
+ {
+ "domain": "Worker",
+ "hidden": true,
+ "types": [],
+ "commands": [
+ {
+ "name": "enable"
+ },
+ {
+ "name": "disable"
+ },
+ {
+ "name": "sendMessageToWorker",
+ "parameters": [
+ { "name": "workerId", "type": "string" },
+ { "name": "message", "type": "string" }
+ ]
+ },
+ {
+ "name": "setWaitForDebuggerOnStart",
+ "parameters": [
+ { "name": "value", "type": "boolean" }
+ ]
+ }
+ ],
+ "events": [
+ {
+ "name": "workerCreated",
+ "parameters": [
+ { "name": "workerId", "type": "string" },
+ { "name": "url", "type": "string" },
+ { "name": "waitingForDebugger", "type": "boolean" }
+ ]
+ },
+ {
+ "name": "workerTerminated",
+ "parameters": [
+ { "name": "workerId", "type": "string" }
+ ]
+ },
+ {
+ "name": "dispatchMessageFromWorker",
+ "parameters": [
+ { "name": "workerId", "type": "string" },
+ { "name": "message", "type": "string" }
+ ]
+ }
+ ]
+ },
+ {
+ "domain": "ServiceWorker",
+ "hidden": true,
+ "types": [
+ {
+ "id": "ServiceWorkerRegistration",
+ "type": "object",
+ "description": "ServiceWorker registration.",
+ "properties": [
+ { "name": "registrationId", "type": "string" },
+ { "name": "scopeURL", "type": "string" },
+ { "name": "isDeleted", "type": "boolean" }
+ ]
+ },
+ {
+ "id": "ServiceWorkerVersionRunningStatus",
+ "type": "string",
+ "enum": ["stopped", "starting", "running", "stopping"]
+ },
+ {
+ "id": "ServiceWorkerVersionStatus",
+ "type": "string",
+ "enum": ["new", "installing", "installed", "activating", "activated", "redundant"]
+ },
+ {
+ "id": "TargetID",
+ "type": "string"
+ },
+ {
+ "id": "ServiceWorkerVersion",
+ "type": "object",
+ "description": "ServiceWorker version.",
+ "properties": [
+ { "name": "versionId", "type": "string" },
+ { "name": "registrationId", "type": "string" },
+ { "name": "scriptURL", "type": "string" },
+ { "name": "runningStatus", "$ref": "ServiceWorkerVersionRunningStatus" },
+ { "name": "status", "$ref": "ServiceWorkerVersionStatus" },
+ { "name": "scriptLastModified", "type": "number", "optional": true, "description": "The Last-Modified header value of the main script." },
+ { "name": "scriptResponseTime", "type": "number", "optional": true, "description": "The time at which the response headers of the main script were received from the server. For cached script it is the last time the cache entry was validated." },
+ { "name": "controlledClients", "type": "array", "optional": true, "items": { "$ref": "TargetID" } }
+ ]
+ },
+ {
+ "id": "ServiceWorkerErrorMessage",
+ "type": "object",
+ "description": "ServiceWorker error message.",
+ "properties": [
+ { "name": "errorMessage", "type": "string" },
+ { "name": "registrationId", "type": "string" },
+ { "name": "versionId", "type": "string" },
+ { "name": "sourceURL", "type": "string" },
+ { "name": "lineNumber", "type": "integer" },
+ { "name": "columnNumber", "type": "integer" }
+ ]
+ },
+ {
+ "id": "TargetInfo",
+ "type": "object",
+ "properties": [
+ { "name": "id", "$ref": "TargetID" },
+ { "name": "type", "type": "string" },
+ { "name": "title", "type": "string" },
+ { "name": "url", "type": "string" }
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "handlers": ["browser"]
+ },
+ {
+ "name": "disable",
+ "handlers": ["browser"]
+ },
+ {
+ "name": "sendMessage",
+ "parameters": [
+ { "name": "workerId", "type": "string" },
+ { "name": "message", "type": "string" }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "stop",
+ "parameters": [
+ { "name": "workerId", "type": "string" }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "unregister",
+ "parameters": [
+ { "name": "scopeURL", "type": "string" }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "updateRegistration",
+ "parameters": [
+ { "name": "scopeURL", "type": "string" }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "startWorker",
+ "parameters": [
+ { "name": "scopeURL", "type": "string" }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "skipWaiting",
+ "parameters": [
+ { "name": "scopeURL", "type": "string" }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "stopWorker",
+ "parameters": [
+ { "name": "versionId", "type": "string" }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "inspectWorker",
+ "parameters": [
+ { "name": "versionId", "type": "string" }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "setForceUpdateOnPageLoad",
+ "parameters": [
+ { "name": "forceUpdateOnPageLoad", "type": "boolean" }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "deliverPushMessage",
+ "parameters": [
+ { "name": "origin", "type": "string" },
+ { "name": "registrationId", "type": "string" },
+ { "name": "data", "type": "string" }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "getTargetInfo",
+ "parameters": [
+ { "name": "targetId", "$ref": "TargetID" }
+ ],
+ "returns": [
+ { "name": "targetInfo","$ref": "TargetInfo" }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "activateTarget",
+ "parameters": [
+ { "name": "targetId", "$ref": "TargetID" }
+ ],
+ "handlers": ["browser"]
+ }
+ ],
+ "events": [
+ {
+ "name": "workerCreated",
+ "parameters": [
+ { "name": "workerId", "type": "string" },
+ { "name": "url", "type": "string" },
+ { "name": "versionId", "type": "string" }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "workerTerminated",
+ "parameters": [
+ { "name": "workerId", "type": "string" }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "dispatchMessage",
+ "parameters": [
+ { "name": "workerId", "type": "string" },
+ { "name": "message", "type": "string" }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "workerRegistrationUpdated",
+ "parameters": [
+ { "name": "registrations", "type": "array", "items": { "$ref": "ServiceWorkerRegistration" } }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "workerVersionUpdated",
+ "parameters": [
+ { "name": "versions", "type": "array", "items": { "$ref": "ServiceWorkerVersion" } }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "workerErrorReported",
+ "parameters": [
+ { "name": "errorMessage", "$ref": "ServiceWorkerErrorMessage" }
+ ],
+ "handlers": ["browser"]
+ }
+ ]
+ },
+ {
+ "domain": "Input",
+ "types": [
+ {
+ "id": "TouchPoint",
+ "type": "object",
+ "hidden": true,
+ "properties": [
+ { "name": "state", "type": "string", "enum": ["touchPressed", "touchReleased", "touchMoved", "touchStationary", "touchCancelled"], "description": "State of the touch point." },
+ { "name": "x", "type": "integer", "description": "X coordinate of the event relative to the main frame's viewport."},
+ { "name": "y", "type": "integer", "description": "Y coordinate of the event relative to the main frame's viewport. 0 refers to the top of the viewport and Y increases as it proceeds towards the bottom of the viewport."},
+ { "name": "radiusX", "type": "integer", "optional": true, "description": "X radius of the touch area (default: 1)."},
+ { "name": "radiusY", "type": "integer", "optional": true, "description": "Y radius of the touch area (default: 1)."},
+ { "name": "rotationAngle", "type": "number", "optional": true, "description": "Rotation angle (default: 0.0)."},
+ { "name": "force", "type": "number", "optional": true, "description": "Force (default: 1.0)."},
+ { "name": "id", "type": "number", "optional": true, "description": "Identifier used to track touch sources between events, must be unique within an event."}
+ ]
+ },
+ {
+ "id": "GestureSourceType",
+ "type": "string",
+ "hidden": true,
+ "enum": ["default", "touch", "mouse"]
+ }
+ ],
+ "commands": [
+ {
+ "name": "dispatchKeyEvent",
+ "parameters": [
+ { "name": "type", "type": "string", "enum": ["keyDown", "keyUp", "rawKeyDown", "char"], "description": "Type of the key event." },
+ { "name": "modifiers", "type": "integer", "optional": true, "description": "Bit field representing pressed modifier keys. Alt=1, Ctrl=2, Meta/Command=4, Shift=8 (default: 0)." },
+ { "name": "timestamp", "type": "number", "optional": true, "description": "Time at which the event occurred. Measured in UTC time in seconds since January 1, 1970 (default: current time)." },
+ { "name": "text", "type": "string", "optional": true, "description": "Text as generated by processing a virtual key code with a keyboard layout. Not needed for for <code>keyUp</code> and <code>rawKeyDown</code> events (default: \"\")" },
+ { "name": "unmodifiedText", "type": "string", "optional": true, "description": "Text that would have been generated by the keyboard if no modifiers were pressed (except for shift). Useful for shortcut (accelerator) key handling (default: \"\")." },
+ { "name": "keyIdentifier", "type": "string", "optional": true, "description": "Unique key identifier (e.g., 'U+0041') (default: \"\")." },
+ { "name": "code", "type": "string", "optional": true, "description": "Unique DOM defined string value for each physical key (e.g., 'KeyA') (default: \"\")." },
+ { "name": "key", "type": "string", "optional": true, "description": "Unique DOM defined string value describing the meaning of the key in the context of active modifiers, keyboard layout, etc (e.g., 'AltGr') (default: \"\")." },
+ { "name": "windowsVirtualKeyCode", "type": "integer", "optional": true, "description": "Windows virtual key code (default: 0)." },
+ { "name": "nativeVirtualKeyCode", "type": "integer", "optional": true, "description": "Native virtual key code (default: 0)." },
+ { "name": "autoRepeat", "type": "boolean", "optional": true, "description": "Whether the event was generated from auto repeat (default: false)." },
+ { "name": "isKeypad", "type": "boolean", "optional": true, "description": "Whether the event was generated from the keypad (default: false)." },
+ { "name": "isSystemKey", "type": "boolean", "optional": true, "description": "Whether the event was a system key event (default: false)." }
+ ],
+ "description": "Dispatches a key event to the page.",
+ "handlers": ["browser"]
+ },
+ {
+ "name": "dispatchMouseEvent",
+ "parameters": [
+ { "name": "type", "type": "string", "enum": ["mousePressed", "mouseReleased", "mouseMoved"], "description": "Type of the mouse event." },
+ { "name": "x", "type": "integer", "description": "X coordinate of the event relative to the main frame's viewport."},
+ { "name": "y", "type": "integer", "description": "Y coordinate of the event relative to the main frame's viewport. 0 refers to the top of the viewport and Y increases as it proceeds towards the bottom of the viewport."},
+ { "name": "modifiers", "type": "integer", "optional": true, "description": "Bit field representing pressed modifier keys. Alt=1, Ctrl=2, Meta/Command=4, Shift=8 (default: 0)." },
+ { "name": "timestamp", "type": "number", "optional": true, "description": "Time at which the event occurred. Measured in UTC time in seconds since January 1, 1970 (default: current time)." },
+ { "name": "button", "type": "string", "enum": ["none", "left", "middle", "right"], "optional": true, "description": "Mouse button (default: \"none\")." },
+ { "name": "clickCount", "type": "integer", "optional": true, "description": "Number of times the mouse button was clicked (default: 0)." }
+ ],
+ "description": "Dispatches a mouse event to the page.",
+ "handlers": ["browser"]
+ },
+ {
+ "name": "dispatchTouchEvent",
+ "hidden": true,
+ "parameters": [
+ { "name": "type", "type": "string", "enum": ["touchStart", "touchEnd", "touchMove"], "description": "Type of the touch event." },
+ { "name": "touchPoints", "type": "array", "items": { "$ref": "TouchPoint" }, "description": "Touch points." },
+ { "name": "modifiers", "type": "integer", "optional": true, "description": "Bit field representing pressed modifier keys. Alt=1, Ctrl=2, Meta/Command=4, Shift=8 (default: 0)." },
+ { "name": "timestamp", "type": "number", "optional": true, "description": "Time at which the event occurred. Measured in UTC time in seconds since January 1, 1970 (default: current time)." }
+ ],
+ "description": "Dispatches a touch event to the page."
+ },
+ {
+ "name": "emulateTouchFromMouseEvent",
+ "hidden": true,
+ "parameters": [
+ { "name": "type", "type": "string", "enum": ["mousePressed", "mouseReleased", "mouseMoved", "mouseWheel"], "description": "Type of the mouse event." },
+ { "name": "x", "type": "integer", "description": "X coordinate of the mouse pointer in DIP."},
+ { "name": "y", "type": "integer", "description": "Y coordinate of the mouse pointer in DIP."},
+ { "name": "timestamp", "type": "number", "description": "Time at which the event occurred. Measured in UTC time in seconds since January 1, 1970." },
+ { "name": "button", "type": "string", "enum": ["none", "left", "middle", "right"], "description": "Mouse button." },
+ { "name": "deltaX", "type": "number", "optional": true, "description": "X delta in DIP for mouse wheel event (default: 0)."},
+ { "name": "deltaY", "type": "number", "optional": true, "description": "Y delta in DIP for mouse wheel event (default: 0)."},
+ { "name": "modifiers", "type": "integer", "optional": true, "description": "Bit field representing pressed modifier keys. Alt=1, Ctrl=2, Meta/Command=4, Shift=8 (default: 0)." },
+ { "name": "clickCount", "type": "integer", "optional": true, "description": "Number of times the mouse button was clicked (default: 0)." }
+ ],
+ "description": "Emulates touch event from the mouse event parameters.",
+ "handlers": ["browser"]
+ },
+ {
+ "name": "synthesizePinchGesture",
+ "async": true,
+ "parameters": [
+ { "name": "x", "type": "integer", "description": "X coordinate of the start of the gesture in CSS pixels." },
+ { "name": "y", "type": "integer", "description": "Y coordinate of the start of the gesture in CSS pixels." },
+ { "name": "scaleFactor", "type": "number", "description": "Relative scale factor after zooming (>1.0 zooms in, <1.0 zooms out)." },
+ { "name": "relativeSpeed", "type": "integer", "optional": true, "description": "Relative pointer speed in pixels per second (default: 800)." },
+ { "name": "gestureSourceType", "$ref": "GestureSourceType", "optional": true, "description": "Which type of input events to be generated (default: 'default', which queries the platform for the preferred input type)." }
+ ],
+ "description": "Synthesizes a pinch gesture over a time period by issuing appropriate touch events.",
+ "hidden": true,
+ "handlers": ["browser"]
+ },
+ {
+ "name": "synthesizeScrollGesture",
+ "async": true,
+ "parameters": [
+ { "name": "x", "type": "integer", "description": "X coordinate of the start of the gesture in CSS pixels." },
+ { "name": "y", "type": "integer", "description": "Y coordinate of the start of the gesture in CSS pixels." },
+ { "name": "xDistance", "type": "integer", "optional": true, "description": "The distance to scroll along the X axis (positive to scroll left)." },
+ { "name": "yDistance", "type": "integer", "optional": true, "description": "The distance to scroll along the Y axis (positive to scroll up)." },
+ { "name": "xOverscroll", "type": "integer", "optional": true, "description": "The number of additional pixels to scroll back along the X axis, in addition to the given distance." },
+ { "name": "yOverscroll", "type": "integer", "optional": true, "description": "The number of additional pixels to scroll back along the Y axis, in addition to the given distance." },
+ { "name": "preventFling", "type": "boolean", "optional": true, "description": "Prevent fling (default: true)." },
+ { "name": "speed", "type": "integer", "optional": true, "description": "Swipe speed in pixels per second (default: 800)." },
+ { "name": "gestureSourceType", "$ref": "GestureSourceType", "optional": true, "description": "Which type of input events to be generated (default: 'default', which queries the platform for the preferred input type)." },
+ { "name": "repeatCount", "type": "integer", "optional": true, "description": "The number of times to repeat the gesture (default: 0)." },
+ { "name": "repeatDelayMs", "type": "integer", "optional": true, "description": "The number of milliseconds delay between each repeat. (default: 250)." },
+ { "name": "interactionMarkerName", "type": "string", "optional": true, "description": "The name of the interaction markers to generate, if not empty (default: \"\")." }
+ ],
+ "description": "Synthesizes a scroll gesture over a time period by issuing appropriate touch events.",
+ "hidden": true,
+ "handlers": ["browser"]
+ },
+ {
+ "name": "synthesizeTapGesture",
+ "async": true,
+ "parameters": [
+ { "name": "x", "type": "integer", "description": "X coordinate of the start of the gesture in CSS pixels." },
+ { "name": "y", "type": "integer", "description": "Y coordinate of the start of the gesture in CSS pixels." },
+ { "name": "duration", "type": "integer", "optional": true, "description": "Duration between touchdown and touchup events in ms (default: 50)." },
+ { "name": "tapCount", "type": "integer", "optional": true, "description": "Number of times to perform the tap (e.g. 2 for double tap, default: 1)." },
+ { "name": "gestureSourceType", "$ref": "GestureSourceType", "optional": true, "description": "Which type of input events to be generated (default: 'default', which queries the platform for the preferred input type)." }
+ ],
+ "description": "Synthesizes a tap gesture over a time period by issuing appropriate touch events.",
+ "hidden": true,
+ "handlers": ["browser"]
+ }
+ ],
+ "events": []
+ },
+ {
+ "domain": "LayerTree",
+ "hidden": true,
+ "types": [
+ {
+ "id": "LayerId",
+ "type": "string",
+ "description": "Unique Layer identifier."
+ },
+ {
+ "id": "SnapshotId",
+ "type": "string",
+ "description": "Unique snapshot identifier."
+ },
+ {
+ "id": "ScrollRect",
+ "type": "object",
+ "description": "Rectangle where scrolling happens on the main thread.",
+ "properties": [
+ { "name": "rect", "$ref": "DOM.Rect", "description": "Rectangle itself." },
+ { "name": "type", "type": "string", "enum": ["RepaintsOnScroll", "TouchEventHandler", "WheelEventHandler"], "description": "Reason for rectangle to force scrolling on the main thread" }
+ ]
+ },
+ {
+ "id": "PictureTile",
+ "type": "object",
+ "description": "Serialized fragment of layer picture along with its offset within the layer.",
+ "properties": [
+ { "name": "x", "type": "number", "description": "Offset from owning layer left boundary" },
+ { "name": "y", "type": "number", "description": "Offset from owning layer top boundary" },
+ { "name": "picture", "type": "string", "description": "Base64-encoded snapshot data." }
+ ]
+ },
+ {
+ "id": "Layer",
+ "type": "object",
+ "description": "Information about a compositing layer.",
+ "properties": [
+ { "name": "layerId", "$ref": "LayerId", "description": "The unique id for this layer." },
+ { "name": "parentLayerId", "$ref": "LayerId", "optional": true, "description": "The id of parent (not present for root)." },
+ { "name": "backendNodeId", "$ref": "DOM.BackendNodeId", "optional": true, "description": "The backend id for the node associated with this layer." },
+ { "name": "offsetX", "type": "number", "description": "Offset from parent layer, X coordinate." },
+ { "name": "offsetY", "type": "number", "description": "Offset from parent layer, Y coordinate." },
+ { "name": "width", "type": "number", "description": "Layer width." },
+ { "name": "height", "type": "number", "description": "Layer height." },
+ { "name": "transform", "type": "array", "items": { "type": "number" }, "minItems": 16, "maxItems": 16, "optional": true, "description": "Transformation matrix for layer, default is identity matrix" },
+ { "name": "anchorX", "type": "number", "optional": true, "description": "Transform anchor point X, absent if no transform specified" },
+ { "name": "anchorY", "type": "number", "optional": true, "description": "Transform anchor point Y, absent if no transform specified" },
+ { "name": "anchorZ", "type": "number", "optional": true, "description": "Transform anchor point Z, absent if no transform specified" },
+ { "name": "paintCount", "type": "integer", "description": "Indicates how many time this layer has painted." },
+ { "name": "drawsContent", "type": "boolean", "description": "Indicates whether this layer hosts any content, rather than being used for transform/scrolling purposes only." },
+ { "name": "invisible", "type": "boolean", "optional": true, "description": "Set if layer is not visible." },
+ { "name": "scrollRects", "type": "array", "items": { "$ref": "ScrollRect"}, "optional": true, "description": "Rectangles scrolling on main thread only."}
+ ]
+ },
+ {
+ "id": "PaintProfile",
+ "type": "array",
+ "description": "Array of timings, one per paint step.",
+ "items": {
+ "type": "number",
+ "description": "A time in seconds since the end of previous step (for the first step, time since painting started)"
+ }
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables compositing tree inspection."
+ },
+ {
+ "name": "disable",
+ "description": "Disables compositing tree inspection."
+ },
+ {
+ "name": "compositingReasons",
+ "parameters": [
+ { "name": "layerId", "$ref": "LayerId", "description": "The id of the layer for which we want to get the reasons it was composited." }
+ ],
+ "description": "Provides the reasons why the given layer was composited.",
+ "returns": [
+ { "name": "compositingReasons", "type": "array", "items": { "type": "string" }, "description": "A list of strings specifying reasons for the given layer to become composited." }
+ ]
+ },
+ {
+ "name": "makeSnapshot",
+ "parameters": [
+ { "name": "layerId", "$ref": "LayerId", "description": "The id of the layer." }
+ ],
+ "description": "Returns the layer snapshot identifier.",
+ "returns": [
+ { "name": "snapshotId", "$ref": "SnapshotId", "description": "The id of the layer snapshot." }
+ ]
+ },
+ {
+ "name": "loadSnapshot",
+ "parameters": [
+ { "name": "tiles", "type": "array", "items": { "$ref": "PictureTile" }, "minItems": 1, "description": "An array of tiles composing the snapshot." }
+ ],
+ "description": "Returns the snapshot identifier.",
+ "returns": [
+ { "name": "snapshotId", "$ref": "SnapshotId", "description": "The id of the snapshot." }
+ ]
+ },
+ {
+ "name": "releaseSnapshot",
+ "parameters": [
+ { "name": "snapshotId", "$ref": "SnapshotId", "description": "The id of the layer snapshot." }
+ ],
+ "description": "Releases layer snapshot captured by the back-end."
+ },
+ {
+ "name": "profileSnapshot",
+ "parameters": [
+ { "name": "snapshotId", "$ref": "SnapshotId", "description": "The id of the layer snapshot." },
+ { "name": "minRepeatCount", "type": "integer", "optional": true, "description": "The maximum number of times to replay the snapshot (1, if not specified)." },
+ { "name": "minDuration", "type": "number", "optional": true, "description": "The minimum duration (in seconds) to replay the snapshot." },
+ { "name": "clipRect", "$ref": "DOM.Rect", "optional": true, "description": "The clip rectangle to apply when replaying the snapshot." }
+ ],
+ "returns": [
+ { "name": "timings", "type": "array", "items": { "$ref": "PaintProfile" }, "description": "The array of paint profiles, one per run." }
+ ]
+ },
+ {
+ "name": "replaySnapshot",
+ "parameters": [
+ { "name": "snapshotId", "$ref": "SnapshotId", "description": "The id of the layer snapshot." },
+ { "name": "fromStep", "type": "integer", "optional": true, "description": "The first step to replay from (replay from the very start if not specified)." },
+ { "name": "toStep", "type": "integer", "optional": true, "description": "The last step to replay to (replay till the end if not specified)." },
+ { "name": "scale", "type": "number", "optional": true, "description": "The scale to apply while replaying (defaults to 1)." }
+ ],
+ "description": "Replays the layer snapshot and returns the resulting bitmap.",
+ "returns": [
+ { "name": "dataURL", "type": "string", "description": "A data: URL for resulting image." }
+ ]
+ },
+ {
+ "name": "snapshotCommandLog",
+ "parameters": [
+ { "name": "snapshotId", "$ref": "SnapshotId", "description": "The id of the layer snapshot." }
+ ],
+ "description": "Replays the layer snapshot and returns canvas log.",
+ "returns": [
+ { "name": "commandLog", "type": "array", "items": { "type": "object" }, "description": "The array of canvas function calls." }
+ ]
+ }
+ ],
+ "events": [
+ {
+ "name": "layerTreeDidChange",
+ "parameters": [
+ { "name": "layers", "type": "array", "items": { "$ref": "Layer" }, "optional": true, "description": "Layer tree, absent if not in the comspositing mode." }
+ ]
+ },
+ {
+ "name": "layerPainted",
+ "parameters": [
+ { "name": "layerId", "$ref": "LayerId", "description": "The id of the painted layer." },
+ { "name": "clip", "$ref": "DOM.Rect", "description": "Clip rectangle." }
+ ]
+ }
+ ]
+ },
+ {
+ "domain": "DeviceOrientation",
+ "hidden": true,
+ "commands": [
+ {
+ "name": "setDeviceOrientationOverride",
+ "description": "Overrides the Device Orientation.",
+ "parameters": [
+ { "name": "alpha", "type": "number", "description": "Mock alpha"},
+ { "name": "beta", "type": "number", "description": "Mock beta"},
+ { "name": "gamma", "type": "number", "description": "Mock gamma"}
+ ]
+ },
+ {
+ "name": "clearDeviceOrientationOverride",
+ "description": "Clears the overridden Device Orientation."
+ }
+ ]
+ },
+ {
+ "domain": "Tracing",
+ "types": [
+ {
+ "id": "MemoryDumpConfig",
+ "type": "object",
+ "description": "Configuration for memory dump. Used only when \"memory-infra\" category is enabled."
+ },
+ {
+ "id": "TraceConfig",
+ "type": "object",
+ "properties": [
+ { "name": "recordMode", "type": "string", "optional": true, "enum": ["recordUntilFull", "recordContinuously", "recordAsMuchAsPossible", "echoToConsole"], "description": "Controls how the trace buffer stores data." },
+ { "name": "enableSampling", "type": "boolean", "optional": true, "description": "Turns on JavaScript stack sampling." },
+ { "name": "enableSystrace", "type": "boolean", "optional": true, "description": "Turns on system tracing." },
+ { "name": "enableArgumentFilter", "type": "boolean", "optional": true, "description": "Turns on argument filter." },
+ { "name": "includedCategories", "type": "array", "items": { "type": "string" }, "optional": true, "description": "Included category filters." },
+ { "name": "excludedCategories", "type": "array", "items": { "type": "string" }, "optional": true, "description": "Excluded category filters." },
+ { "name": "syntheticDelays", "type": "array", "items": { "type": "string" }, "optional": true, "description": "Configuration to synthesize the delays in tracing." },
+ { "name": "memoryDumpConfig", "$ref": "MemoryDumpConfig", "optional": true, "description": "Configuration for memory dump triggers. Used only when \"memory-infra\" category is enabled." }
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "start",
+ "async": true,
+ "description": "Start trace events collection.",
+ "parameters": [
+ { "name": "categories", "type": "string", "optional": true, "deprecated": true, "description": "Category/tag filter" },
+ { "name": "options", "type": "string", "optional": true, "deprecated": true, "description": "Tracing options" },
+ { "name": "bufferUsageReportingInterval", "type": "number", "optional": true, "description": "If set, the agent will issue bufferUsage events at this interval, specified in milliseconds" },
+ { "name": "transferMode", "type": "string", "enum": ["ReportEvents", "ReturnAsStream"], "optional": true, "description": "Whether to report trace events as series of dataCollected events or to save trace to a stream (defaults to <code>ReportEvents</code>)." },
+ { "name": "traceConfig", "$ref": "TraceConfig", "optional": true, "description": "" }
+ ],
+ "handlers": ["browser", "renderer"]
+ },
+ {
+ "name": "end",
+ "async": true,
+ "description": "Stop trace events collection.",
+ "handlers": ["browser", "renderer"]
+ },
+ {
+ "name": "getCategories",
+ "async": true,
+ "description": "Gets supported tracing categories.",
+ "returns": [
+ { "name": "categories", "type": "array", "items": { "type": "string" }, "description": "A list of supported tracing categories." }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "requestMemoryDump",
+ "async": true,
+ "description": "Request a global memory dump.",
+ "returns": [
+ { "name": "dumpGuid", "type": "string", "description": "GUID of the resulting global memory dump." },
+ { "name": "success", "type": "boolean", "description": "True iff the global memory dump succeeded." }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "recordClockSyncMarker",
+ "description": "Record a clock sync marker in the trace.",
+ "parameters": [
+ { "name": "syncId", "type": "string", "description": "The ID of this clock sync marker" }
+ ],
+ "handlers": ["browser"]
+ }
+ ],
+ "events": [
+ {
+ "name": "dataCollected",
+ "parameters": [
+ { "name": "value", "type": "array", "items": { "type": "object" } }
+ ],
+ "description": "Contains an bucket of collected trace events. When tracing is stopped collected events will be send as a sequence of dataCollected events followed by tracingComplete event.",
+ "handlers": ["browser"]
+ },
+ {
+ "name": "tracingComplete",
+ "description": "Signals that tracing is stopped and there is no trace buffers pending flush, all data were delivered via dataCollected events.",
+ "parameters": [
+ { "name": "stream", "$ref": "IO.StreamHandle", "optional": true, "description": "A handle of the stream that holds resulting trace data." }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "bufferUsage",
+ "parameters": [
+ { "name": "percentFull", "type": "number", "optional": true, "description": "A number in range [0..1] that indicates the used size of event buffer as a fraction of its total size." },
+ { "name": "eventCount", "type": "number", "optional": true, "description": "An approximate number of events in the trace log." },
+ { "name": "value", "type": "number", "optional": true, "description": "A number in range [0..1] that indicates the used size of event buffer as a fraction of its total size." }
+ ],
+ "handlers": ["browser"]
+ }
+ ]
+ },
+ {
+ "domain": "Animation",
+ "hidden": true,
+ "types": [
+ {
+ "id": "Animation",
+ "type": "object",
+ "hidden": true,
+ "properties": [
+ { "name": "id", "type": "string", "description": "<code>Animation</code>'s id." },
+ { "name": "name", "type": "string", "description": "<code>Animation</code>'s name." },
+ { "name": "pausedState", "type": "boolean", "hidden": "true", "description": "<code>Animation</code>'s internal paused state." },
+ { "name": "playState", "type": "string", "description": "<code>Animation</code>'s play state." },
+ { "name": "playbackRate", "type": "number", "description": "<code>Animation</code>'s playback rate." },
+ { "name": "startTime", "type": "number", "description": "<code>Animation</code>'s start time." },
+ { "name": "currentTime", "type": "number", "description": "<code>Animation</code>'s current time." },
+ { "name": "source", "$ref": "AnimationEffect", "description": "<code>Animation</code>'s source animation node." },
+ { "name": "type", "type": "string", "enum": ["CSSTransition", "CSSAnimation", "WebAnimation"], "description": "Animation type of <code>Animation</code>." },
+ { "name": "cssId", "type": "string", "optional": true, "description": "A unique ID for <code>Animation</code> representing the sources that triggered this CSS animation/transition."}
+ ],
+ "description": "Animation instance."
+ },
+ {
+ "id": "AnimationEffect",
+ "type": "object",
+ "hidden": true,
+ "properties": [
+ { "name": "delay", "type": "number", "description": "<code>AnimationEffect</code>'s delay." },
+ { "name": "endDelay", "type": "number", "description": "<code>AnimationEffect</code>'s end delay." },
+ { "name": "playbackRate", "type": "number", "description": "<code>AnimationEffect</code>'s playbackRate." },
+ { "name": "iterationStart", "type": "number", "description": "<code>AnimationEffect</code>'s iteration start." },
+ { "name": "iterations", "type": "number", "description": "<code>AnimationEffect</code>'s iterations." },
+ { "name": "duration", "type": "number", "description": "<code>AnimationEffect</code>'s iteration duration." },
+ { "name": "direction", "type": "string", "description": "<code>AnimationEffect</code>'s playback direction." },
+ { "name": "fill", "type": "string", "description": "<code>AnimationEffect</code>'s fill mode." },
+ { "name": "backendNodeId", "$ref": "DOM.BackendNodeId", "description": "<code>AnimationEffect</code>'s target node." },
+ { "name": "keyframesRule", "$ref": "KeyframesRule", "optional": true, "description": "<code>AnimationEffect</code>'s keyframes." },
+ { "name": "easing", "type": "string", "description": "<code>AnimationEffect</code>'s timing function." }
+ ],
+ "description": "AnimationEffect instance"
+ },
+ {
+ "id": "KeyframesRule",
+ "type": "object",
+ "properties": [
+ { "name": "name", "type": "string", "optional": true, "description": "CSS keyframed animation's name." },
+ { "name": "keyframes", "type": "array", "items": { "$ref": "KeyframeStyle" }, "description": "List of animation keyframes." }
+ ],
+ "description": "Keyframes Rule"
+ },
+ {
+ "id": "KeyframeStyle",
+ "type": "object",
+ "properties": [
+ { "name": "offset", "type": "string", "description": "Keyframe's time offset." },
+ { "name": "easing", "type": "string", "description": "<code>AnimationEffect</code>'s timing function." }
+ ],
+ "description": "Keyframe Style"
+ }
+ ],
+ "commands": [
+ {
+ "name": "enable",
+ "description": "Enables animation domain notifications."
+ },
+ {
+ "name": "disable",
+ "description": "Disables animation domain notifications."
+ },
+ {
+ "name": "getPlaybackRate",
+ "returns": [
+ { "name": "playbackRate", "type": "number", "description": "Playback rate for animations on page."}
+ ],
+ "description": "Gets the playback rate of the document timeline."
+ },
+ {
+ "name": "setPlaybackRate",
+ "parameters": [
+ { "name": "playbackRate", "type": "number", "description": "Playback rate for animations on page" }
+ ],
+ "description": "Sets the playback rate of the document timeline."
+ },
+ {
+ "name": "getCurrentTime",
+ "parameters": [
+ { "name": "id", "type": "string", "description": "Id of animation." }
+ ],
+ "returns": [
+ { "name": "currentTime", "type": "number", "description": "Current time of the page." }
+ ],
+ "description": "Returns the current time of the an animation."
+ },
+ {
+ "name": "setPaused",
+ "parameters": [
+ { "name": "animations", "type": "array", "items": { "type": "string" }, "description": "Animations to set the pause state of." },
+ { "name": "paused", "type": "boolean", "description": "Paused state to set to." }
+ ],
+ "description": "Sets the paused state of a set of animations."
+ },
+ {
+ "name": "setTiming",
+ "parameters": [
+ { "name": "animationId", "type": "string", "description": "Animation id." },
+ { "name": "duration", "type": "number", "description": "Duration of the animation." },
+ { "name": "delay", "type": "number", "description": "Delay of the animation." }
+ ],
+ "description": "Sets the timing of an animation node."
+ },
+ {
+ "name": "seekAnimations",
+ "parameters": [
+ { "name": "animations", "type": "array", "items": { "type": "string" }, "description": "List of animation ids to seek." },
+ { "name": "currentTime", "type": "number", "description": "Set the current time of each animation." }
+ ],
+ "description": "Seek a set of animations to a particular time within each animation."
+ },
+ {
+ "name": "releaseAnimations",
+ "parameters": [
+ { "name": "animations", "type": "array", "items": { "type": "string" }, "description": "List of animation ids to seek." }
+ ],
+ "description": "Releases a set of animations to no longer be manipulated."
+ },
+ {
+ "name": "resolveAnimation",
+ "parameters": [
+ { "name": "animationId", "type": "string", "description": "Animation id." }
+ ],
+ "returns": [
+ { "name": "remoteObject", "$ref": "Runtime.RemoteObject", "description": "Corresponding remote object." }
+ ],
+ "description": "Gets the remote object of the Animation."
+ }
+ ],
+ "events": [
+ {
+ "name": "animationCreated",
+ "parameters": [
+ { "name": "id", "type": "string", "description": "Id of the animation that was created." }
+ ],
+ "description": "Event for each animation that has been created."
+ },
+ {
+ "name": "animationStarted",
+ "parameters": [
+ { "name": "animation", "$ref": "Animation", "description": "Animation that was started." }
+ ],
+ "description": "Event for animation that has been started."
+ },
+ {
+ "name": "animationCanceled",
+ "parameters": [
+ { "name": "id", "type": "string", "description": "Id of the animation that was cancelled."}
+ ],
+ "description": "Event for when an animation has been cancelled."
+ }
+ ]
+ },
+ {
+ "domain": "Accessibility",
+ "hidden": true,
+ "types": [
+ {
+ "id": "AXNodeId",
+ "type": "string",
+ "description": "Unique accessibility node identifier."
+ },
+ {
+ "id": "AXValueType",
+ "type": "string",
+ "enum": [ "boolean", "tristate", "booleanOrUndefined", "idref", "idrefList", "integer", "node", "nodeList", "number", "string", "computedString", "token", "tokenList", "domRelation", "role", "internalRole", "valueUndefined" ],
+ "description": "Enum of possible property types."
+ },
+ {
+ "id": "AXValueSourceType",
+ "type": "string",
+ "enum": [ "attribute", "implicit", "style", "contents", "placeholder", "relatedElement" ],
+ "description": "Enum of possible property sources."
+ },
+ { "id": "AXValueNativeSourceType",
+ "type": "string",
+ "enum": [ "figcaption", "label", "labelfor", "labelwrapped", "legend", "tablecaption", "title", "other" ],
+ "description": "Enum of possible native property sources (as a subtype of a particular AXValueSourceType)."
+ },
+ {
+ "id": "AXValueSource",
+ "type": "object",
+ "properties": [
+ { "name": "type", "$ref": "AXValueSourceType", "description": "What type of source this is." },
+ { "name": "value", "$ref": "AXValue", "description": "The value of this property source.", "optional": true },
+ { "name": "attribute", "type": "string", "description": "The name of the relevant attribute, if any.", "optional": true },
+ { "name": "attributeValue", "$ref": "AXValue", "description": "The value of the relevant attribute, if any.", "optional": true },
+ { "name": "superseded", "type": "boolean", "description": "Whether this source is superseded by a higher priority source.", "optional": true },
+ { "name": "nativeSource", "$ref": "AXValueNativeSourceType", "description": "The native markup source for this value, e.g. a <label> element.", "optional": true },
+ { "name": "nativeSourceValue", "$ref": "AXValue", "description": "The value, such as a node or node list, of the native source.", "optional": true },
+ { "name": "invalid", "type": "boolean", "description": "Whether the value for this property is invalid.", "optional": true },
+ { "name": "invalidReason", "type": "string", "description": "Reason for the value being invalid, if it is.", "optional": true }
+ ],
+ "description": "A single source for a computed AX property."
+ },
+ {
+ "id": "AXRelatedNode",
+ "type": "object",
+ "properties": [
+ { "name": "backendNodeId", "$ref": "DOM.BackendNodeId", "description": "The BackendNodeId of the related node." },
+ { "name": "idref", "type": "string", "description": "The IDRef value provided, if any.", "optional": true },
+ { "name": "text", "type": "string", "description": "The text alternative of this node in the current context.", "optional": true }
+ ]
+ },
+ {
+ "id": "AXProperty",
+ "type": "object",
+ "properties": [
+ { "name": "name", "type": "string", "description": "The name of this property." },
+ { "name": "value", "$ref": "AXValue", "description": "The value of this property." }
+ ]
+ },
+ {
+ "id": "AXValue",
+ "type": "object",
+ "properties": [
+ { "name": "type", "$ref": "AXValueType", "description": "The type of this value." },
+
+ { "name": "value", "type": "any", "description": "The computed value of this property.", "optional": true },
+ { "name": "relatedNodes", "type": "array", "items": { "$ref": "AXRelatedNode" }, "description": "One or more related nodes, if applicable.", "optional": true },
+ { "name": "sources", "type": "array", "items": { "$ref": "AXValueSource" }, "description": "The sources which contributed to the computation of this property.", "optional": true }
+ ],
+ "description": "A single computed AX property."
+ },
+ {
+ "id": "AXGlobalStates",
+ "type": "string",
+ "enum": [ "disabled", "hidden", "hiddenRoot", "invalid" ],
+ "description": "States which apply to every AX node."
+ },
+ {
+ "id": "AXLiveRegionAttributes",
+ "type": "string",
+ "enum": [ "live", "atomic", "relevant", "busy", "root" ],
+ "description": "Attributes which apply to nodes in live regions."
+ },
+ {
+ "id": "AXWidgetAttributes",
+ "type": "string",
+ "enum": [ "autocomplete", "haspopup", "level", "multiselectable", "orientation", "multiline", "readonly", "required", "valuemin", "valuemax", "valuetext" ],
+ "Description": "Attributes which apply to widgets."
+ },
+ {
+ "id": "AXWidgetStates",
+ "type": "string",
+ "enum": [ "checked", "expanded", "pressed", "selected" ],
+ "description": "States which apply to widgets."
+ },
+ {
+ "id": "AXRelationshipAttributes",
+ "type": "string",
+ "enum": [ "activedescendant", "flowto", "controls", "describedby", "labelledby", "owns" ],
+ "description": "Relationships between elements other than parent/child/sibling."
+ },
+ {
+ "id": "AXNode",
+ "type": "object",
+ "properties": [
+ { "name": "nodeId", "$ref": "AXNodeId", "description": "Unique identifier for this node." },
+ { "name": "ignored", "type": "boolean", "description": "Whether this node is ignored for accessibility" },
+ { "name": "ignoredReasons", "type": "array", "items": { "$ref": "AXProperty" }, "description": "Collection of reasons why this node is hidden.", "optional": true },
+ { "name": "role", "$ref": "AXValue", "description": "This <code>Node</code>'s role, whether explicit or implicit.", "optional": true},
+ { "name": "name", "$ref": "AXValue", "description": "The accessible name for this <code>Node</code>.", "optional": true },
+ { "name": "description", "$ref": "AXValue", "description": "The accessible description for this <code>Node</code>.", "optional": true },
+ { "name": "value", "$ref": "AXValue", "description": "The value for this <code>Node</code>.", "optional": true },
+ { "name": "properties", "type": "array", "items": { "$ref": "AXProperty" }, "description": "All other properties", "optional": true }
+ ],
+ "description": "A node in the accessibility tree."
+ }
+ ],
+ "commands": [
+ {
+ "name": "getAXNode",
+ "parameters": [
+ { "name": "nodeId", "$ref": "DOM.NodeId", "description": "ID of node to get accessibility node for." }
+ ],
+ "returns": [
+ { "name": "accessibilityNode", "$ref": "AXNode", "description": "The <code>Accessibility.AXNode</code> for this DOM node, if it exists.", "optional": true }
+ ],
+ "description": "Fetches the accessibility node for this DOM node, if it exists.",
+ "hidden": true
+ }
+ ]
+ },
+ {
+ "domain": "Storage",
+ "hidden": true,
+ "types": [
+ {
+ "id": "StorageType",
+ "type": "string",
+ "enum": [
+ "appcache",
+ "cookies",
+ "file_systems",
+ "indexeddb",
+ "local_storage",
+ "shader_cache",
+ "websql",
+ "webrtc_indetity",
+ "service_workers",
+ "cache_storage",
+ "all"
+ ],
+ "description": "Enum of possible storage types."
+ }
+ ],
+ "commands": [
+ {
+ "name": "clearDataForOrigin",
+ "parameters": [
+ { "name": "origin", "type": "string", "description": "Security origin." },
+ { "name": "storageTypes", "type": "string", "description": "Comma separated origin names." }
+ ],
+ "description": "Clears storage for origin.",
+ "handlers": ["browser"]
+ }
+ ]
+ }]
+}
diff --git a/deps/v8_inspector/platform/PlatformExport.h b/deps/v8_inspector/platform/PlatformExport.h
new file mode 100644
index 0000000000..8230fbb80f
--- /dev/null
+++ b/deps/v8_inspector/platform/PlatformExport.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef PlatformExport_h
+#define PlatformExport_h
+
+#if !defined(BLINK_PLATFORM_IMPLEMENTATION)
+#define BLINK_PLATFORM_IMPLEMENTATION 0
+#endif
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+#if BLINK_PLATFORM_IMPLEMENTATION
+#define PLATFORM_EXPORT __declspec(dllexport)
+#else
+#define PLATFORM_EXPORT __declspec(dllimport)
+#endif
+#else // defined(WIN32)
+#define PLATFORM_EXPORT __attribute__((visibility("default")))
+#endif
+#else // defined(COMPONENT_BUILD)
+#define PLATFORM_EXPORT
+#endif
+
+#if defined(_MSC_VER)
+// MSVC Compiler warning C4275:
+// non dll-interface class 'Bar' used as base for dll-interface class 'Foo'.
+// Note that this is intended to be used only when no access to the base class'
+// static data is done through derived classes or inline methods. For more info,
+// see http://msdn.microsoft.com/en-us/library/3tdb471s(VS.80).aspx
+//
+// This pragma will allow exporting a class that inherits from a non-exported
+// base class, anywhere in the Blink platform component. This is only
+// a problem when using the MSVC compiler on Windows.
+#pragma warning(suppress:4275)
+#endif
+
+#endif // PlatformExport_h
diff --git a/deps/v8_inspector/platform/inspector_protocol/Allocator.h b/deps/v8_inspector/platform/inspector_protocol/Allocator.h
new file mode 100644
index 0000000000..e38b76cd62
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/Allocator.h
@@ -0,0 +1,22 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef Allocator_h
+#define Allocator_h
+
+enum NotNullTagEnum { NotNullLiteral };
+
+#define PROTOCOL_DISALLOW_NEW() \
+ private: \
+ void* operator new(size_t) = delete; \
+ void* operator new(size_t, NotNullTagEnum, void*) = delete; \
+ void* operator new(size_t, void*) = delete; \
+ public:
+
+#define PROTOCOL_DISALLOW_COPY(ClassName) \
+ private: \
+ ClassName(const ClassName&) = delete; \
+ ClassName& operator=(const ClassName&) = delete
+
+#endif /* Allocator_h */
diff --git a/deps/v8_inspector/platform/inspector_protocol/Array.h b/deps/v8_inspector/platform/inspector_protocol/Array.h
new file mode 100644
index 0000000000..07a2993d5c
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/Array.h
@@ -0,0 +1,137 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef Array_h
+#define Array_h
+
+#include "platform/PlatformExport.h"
+#include "platform/inspector_protocol/Collections.h"
+#include "platform/inspector_protocol/ErrorSupport.h"
+#include "platform/inspector_protocol/String16.h"
+#include "platform/inspector_protocol/ValueConversions.h"
+#include "platform/inspector_protocol/Values.h"
+
+namespace blink {
+namespace protocol {
+
+template<typename T>
+class ArrayBase {
+public:
+ static std::unique_ptr<Array<T>> create()
+ {
+ return wrapUnique(new Array<T>());
+ }
+
+ static std::unique_ptr<Array<T>> parse(protocol::Value* value, ErrorSupport* errors)
+ {
+ protocol::ListValue* array = ListValue::cast(value);
+ if (!array) {
+ errors->addError("array expected");
+ return nullptr;
+ }
+ errors->push();
+ std::unique_ptr<Array<T>> result(new Array<T>());
+ for (size_t i = 0; i < array->size(); ++i) {
+ errors->setName(String16::number(i));
+ T item = FromValue<T>::parse(array->at(i), errors);
+ result->m_vector.append(item);
+ }
+ errors->pop();
+ if (errors->hasErrors())
+ return nullptr;
+ return result;
+ }
+
+ void addItem(const T& value)
+ {
+ m_vector.append(value);
+ }
+
+ size_t length()
+ {
+ return m_vector.size();
+ }
+
+ T get(size_t index)
+ {
+ return m_vector[index];
+ }
+
+ std::unique_ptr<protocol::ListValue> serialize()
+ {
+ std::unique_ptr<protocol::ListValue> result = ListValue::create();
+ for (auto& item : m_vector)
+ result->pushValue(toValue(item));
+ return result;
+ }
+
+private:
+ protocol::Vector<T> m_vector;
+};
+
+template<> class Array<String> : public ArrayBase<String> {};
+template<> class Array<String16> : public ArrayBase<String16> {};
+template<> class Array<int> : public ArrayBase<int> {};
+template<> class Array<double> : public ArrayBase<double> {};
+template<> class Array<bool> : public ArrayBase<bool> {};
+
+template<typename T>
+class Array {
+public:
+ static std::unique_ptr<Array<T>> create()
+ {
+ return wrapUnique(new Array<T>());
+ }
+
+ static std::unique_ptr<Array<T>> parse(protocol::Value* value, ErrorSupport* errors)
+ {
+ protocol::ListValue* array = ListValue::cast(value);
+ if (!array) {
+ errors->addError("array expected");
+ return nullptr;
+ }
+ std::unique_ptr<Array<T>> result = wrapUnique(new Array<T>());
+ errors->push();
+ for (size_t i = 0; i < array->size(); ++i) {
+ errors->setName(String16::number(i));
+ std::unique_ptr<T> item = FromValue<T>::parse(array->at(i), errors);
+ result->m_vector.append(std::move(item));
+ }
+ errors->pop();
+ if (errors->hasErrors())
+ return nullptr;
+ return result;
+ }
+
+ void addItem(std::unique_ptr<T> value)
+ {
+ m_vector.append(std::move(value));
+ }
+
+ size_t length()
+ {
+ return m_vector.size();
+ }
+
+ T* get(size_t index)
+ {
+ return m_vector[index];
+ }
+
+ std::unique_ptr<protocol::ListValue> serialize()
+ {
+ std::unique_ptr<protocol::ListValue> result = ListValue::create();
+ for (auto& item : m_vector)
+ result->pushValue(toValue(item));
+ return result;
+ }
+
+private:
+ protocol::Vector<std::unique_ptr<T>> m_vector;
+};
+
+} // namespace platform
+} // namespace blink
+
+#endif // !defined(Array_h)
diff --git a/deps/v8_inspector/platform/inspector_protocol/Backend_cpp.template b/deps/v8_inspector/platform/inspector_protocol/Backend_cpp.template
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/Backend_cpp.template
diff --git a/deps/v8_inspector/platform/inspector_protocol/Backend_h.template b/deps/v8_inspector/platform/inspector_protocol/Backend_h.template
new file mode 100644
index 0000000000..4d6ac711f6
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/Backend_h.template
@@ -0,0 +1,78 @@
+// This file is generated
+
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef {{class_name}}_h
+#define {{class_name}}_h
+
+#include "platform/inspector_protocol/TypeBuilder.h"
+
+namespace blink {
+namespace protocol {
+
+class FrontendChannel;
+class BackendImplWeakPtr;
+
+class PLATFORM_EXPORT Backend {
+public:
+ class PLATFORM_EXPORT CallbackBase {
+ public:
+ virtual ~CallbackBase() { }
+ virtual void sendFailure(const ErrorString&) = 0;
+ };
+{% for domain in api.domains %}
+
+ class PLATFORM_EXPORT {{domain.domain}} {
+ public:
+ {% for command in domain.commands %}
+ {% if "redirect" in command %}{% continue %}{% endif %}
+ {% if ("handlers" in command) and not ("renderer" in command["handlers"]) %}{% continue %}{% endif %}
+ {% if "async" in command %}
+ class PLATFORM_EXPORT {{command.name | to_title_case}}Callback : public CallbackBase {
+ public:
+ virtual void sendSuccess(
+ {%- for parameter in command.returns -%}
+ {%- if "optional" in parameter -%}
+ const Maybe<{{resolve_type(parameter).raw_type}}>& {{parameter.name}}
+ {%- else -%}
+ {{resolve_type(parameter).pass_type}} {{parameter.name}}
+ {%- endif -%}
+ {%- if not loop.last -%}, {% endif -%}
+ {%- endfor -%}
+ ) = 0;
+ };
+ {% endif %}
+ virtual void {{command.name}}(ErrorString*
+ {%- for parameter in command.parameters -%}
+ {%- if "optional" in parameter -%}
+ , const Maybe<{{resolve_type(parameter).raw_type}}>& in_{{parameter.name}}
+ {%- else -%}
+ , {{resolve_type(parameter).pass_type}} in_{{parameter.name}}
+ {%- endif -%}
+ {%- endfor -%}
+ {%- if "async" in command -%}
+ , std::unique_ptr<{{command.name | to_title_case}}Callback> callback
+ {%- else -%}
+ {%- for parameter in command.returns -%}
+ {%- if "optional" in parameter -%}
+ , Maybe<{{resolve_type(parameter).raw_type}}>* out_{{parameter.name}}
+ {%- else -%}
+ , {{resolve_type(parameter).type}}* out_{{parameter.name}}
+ {%- endif -%}
+ {%- endfor -%}
+ {%- endif -%}
+ ) = 0;
+ {% endfor %}
+
+ protected:
+ virtual ~{{domain.domain}}() { }
+ };
+{% endfor %}
+};
+
+} // namespace protocol
+} // namespace blink
+
+#endif // !defined({{class_name}}_h)
diff --git a/deps/v8_inspector/platform/inspector_protocol/CodeGenerator.py b/deps/v8_inspector/platform/inspector_protocol/CodeGenerator.py
new file mode 100644
index 0000000000..5107feb680
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/CodeGenerator.py
@@ -0,0 +1,308 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os.path
+import sys
+import string
+import optparse
+import re
+try:
+ import json
+except ImportError:
+ import simplejson as json
+
+# Path handling for libraries and templates
+# Paths have to be normalized because Jinja uses the exact template path to
+# determine the hash used in the cache filename, and we need a pre-caching step
+# to be concurrency-safe. Use absolute path because __file__ is absolute if
+# module is imported, and relative if executed directly.
+# If paths differ between pre-caching and individual file compilation, the cache
+# is regenerated, which causes a race condition and breaks concurrent build,
+# since some compile processes will try to read the partially written cache.
+module_path, module_filename = os.path.split(os.path.realpath(__file__))
+templates_dir = module_path
+deps_dir = os.path.normpath(os.path.join(
+ module_path, os.pardir, os.pardir, 'deps'))
+
+sys.path.insert(1, os.path.join(deps_dir, "jinja2"))
+sys.path.insert(1, os.path.join(deps_dir, "markupsafe"))
+import jinja2
+
+cmdline_parser = optparse.OptionParser()
+cmdline_parser.add_option("--output_dir")
+cmdline_parser.add_option("--generate_dispatcher")
+
+try:
+ arg_options, arg_values = cmdline_parser.parse_args()
+ if (len(arg_values) == 0):
+ raise Exception("At least one plain argument expected (found %s)" % len(arg_values))
+ output_dirname = arg_options.output_dir
+ generate_dispatcher = arg_options.generate_dispatcher
+ if not output_dirname:
+ raise Exception("Output directory must be specified")
+except Exception:
+ # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.html
+ exc = sys.exc_info()[1]
+ sys.stderr.write("Failed to parse command-line arguments: %s\n\n" % exc)
+ sys.stderr.write("Usage: <script> --output_dir <output_dir> blink_protocol.json v8_protocol.json ...\n")
+ exit(1)
+
+json_api = {"domains": []}
+
+json_timestamp = 0
+
+for filename in arg_values:
+ json_timestamp = max(os.path.getmtime(filename), json_timestamp)
+ input_file = open(filename, "r")
+ json_string = input_file.read()
+ parsed_json = json.loads(json_string)
+ json_api["domains"] += parsed_json["domains"]
+
+def to_title_case(name):
+ return name[:1].upper() + name[1:]
+
+
+def dash_to_camelcase(word):
+ return ''.join(to_title_case(x) or '-' for x in word.split('-'))
+
+
+def initialize_jinja_env(cache_dir):
+ jinja_env = jinja2.Environment(
+ loader=jinja2.FileSystemLoader(templates_dir),
+ # Bytecode cache is not concurrency-safe unless pre-cached:
+ # if pre-cached this is read-only, but writing creates a race condition.
+ bytecode_cache=jinja2.FileSystemBytecodeCache(cache_dir),
+ keep_trailing_newline=True, # newline-terminate generated files
+ lstrip_blocks=True, # so can indent control flow tags
+ trim_blocks=True)
+ jinja_env.filters.update({"to_title_case": to_title_case, "dash_to_camelcase": dash_to_camelcase})
+ jinja_env.add_extension('jinja2.ext.loopcontrols')
+ return jinja_env
+
+
+def output_file(file_name):
+ return open(file_name, "w")
+
+
+def patch_full_qualified_refs():
+ def patch_full_qualified_refs_in_domain(json, domain_name):
+ if isinstance(json, list):
+ for item in json:
+ patch_full_qualified_refs_in_domain(item, domain_name)
+
+ if not isinstance(json, dict):
+ return
+ for key in json:
+ if key == "type" and json[key] == "string":
+ json[key] = domain_name + ".string"
+ if key != "$ref":
+ patch_full_qualified_refs_in_domain(json[key], domain_name)
+ continue
+ if json["$ref"].find(".") == -1:
+ json["$ref"] = domain_name + "." + json["$ref"]
+
+ for domain in json_api["domains"]:
+ patch_full_qualified_refs_in_domain(domain, domain["domain"])
+
+
+def create_user_type_definition(domain_name, type):
+ return {
+ "return_type": "std::unique_ptr<protocol::%s::%s>" % (domain_name, type["id"]),
+ "pass_type": "std::unique_ptr<protocol::%s::%s>" % (domain_name, type["id"]),
+ "to_raw_type": "%s.get()",
+ "to_pass_type": "std::move(%s)",
+ "to_rvalue": "std::move(%s)",
+ "type": "std::unique_ptr<protocol::%s::%s>" % (domain_name, type["id"]),
+ "raw_type": "protocol::%s::%s" % (domain_name, type["id"]),
+ "raw_pass_type": "protocol::%s::%s*" % (domain_name, type["id"]),
+ "raw_return_type": "protocol::%s::%s*" % (domain_name, type["id"]),
+ }
+
+
+def create_object_type_definition():
+ return {
+ "return_type": "std::unique_ptr<protocol::DictionaryValue>",
+ "pass_type": "std::unique_ptr<protocol::DictionaryValue>",
+ "to_raw_type": "%s.get()",
+ "to_pass_type": "std::move(%s)",
+ "to_rvalue": "std::move(%s)",
+ "type": "std::unique_ptr<protocol::DictionaryValue>",
+ "raw_type": "protocol::DictionaryValue",
+ "raw_pass_type": "protocol::DictionaryValue*",
+ "raw_return_type": "protocol::DictionaryValue*",
+ }
+
+
+def create_any_type_definition():
+ return {
+ "return_type": "std::unique_ptr<protocol::Value>",
+ "pass_type": "std::unique_ptr<protocol::Value>",
+ "to_raw_type": "%s.get()",
+ "to_pass_type": "std::move(%s)",
+ "to_rvalue": "std::move(%s)",
+ "type": "std::unique_ptr<protocol::Value>",
+ "raw_type": "protocol::Value",
+ "raw_pass_type": "protocol::Value*",
+ "raw_return_type": "protocol::Value*",
+ }
+
+
+def create_string_type_definition(domain):
+ if domain in ["Runtime", "Debugger", "Profiler", "HeapProfiler"]:
+ return {
+ "return_type": "String16",
+ "pass_type": "const String16&",
+ "to_pass_type": "%s",
+ "to_raw_type": "%s",
+ "to_rvalue": "%s",
+ "type": "String16",
+ "raw_type": "String16",
+ "raw_pass_type": "const String16&",
+ "raw_return_type": "String16",
+ }
+ return {
+ "return_type": "String",
+ "pass_type": "const String&",
+ "to_pass_type": "%s",
+ "to_raw_type": "%s",
+ "to_rvalue": "%s",
+ "type": "String",
+ "raw_type": "String",
+ "raw_pass_type": "const String&",
+ "raw_return_type": "String",
+ }
+
+
+def create_primitive_type_definition(type):
+ typedefs = {
+ "number": "double",
+ "integer": "int",
+ "boolean": "bool"
+ }
+ jsontypes = {
+ "number": "TypeNumber",
+ "integer": "TypeNumber",
+ "boolean": "TypeBoolean",
+ }
+ return {
+ "return_type": typedefs[type],
+ "pass_type": typedefs[type],
+ "to_pass_type": "%s",
+ "to_raw_type": "%s",
+ "to_rvalue": "%s",
+ "type": typedefs[type],
+ "raw_type": typedefs[type],
+ "raw_pass_type": typedefs[type],
+ "raw_return_type": typedefs[type],
+ }
+
+type_definitions = {}
+type_definitions["number"] = create_primitive_type_definition("number")
+type_definitions["integer"] = create_primitive_type_definition("integer")
+type_definitions["boolean"] = create_primitive_type_definition("boolean")
+type_definitions["object"] = create_object_type_definition()
+type_definitions["any"] = create_any_type_definition()
+
+def wrap_array_definition(type):
+ return {
+ "return_type": "std::unique_ptr<protocol::Array<%s>>" % type["raw_type"],
+ "pass_type": "std::unique_ptr<protocol::Array<%s>>" % type["raw_type"],
+ "to_raw_type": "%s.get()",
+ "to_pass_type": "std::move(%s)",
+ "to_rvalue": "std::move(%s)",
+ "type": "std::unique_ptr<protocol::Array<%s>>" % type["raw_type"],
+ "raw_type": "protocol::Array<%s>" % type["raw_type"],
+ "raw_pass_type": "protocol::Array<%s>*" % type["raw_type"],
+ "raw_return_type": "protocol::Array<%s>*" % type["raw_type"],
+ "create_type": "wrapUnique(new protocol::Array<%s>())" % type["raw_type"],
+ "out_type": "protocol::Array<%s>&" % type["raw_type"],
+ }
+
+
+def create_type_definitions():
+ for domain in json_api["domains"]:
+ type_definitions[domain["domain"] + ".string"] = create_string_type_definition(domain["domain"])
+ if not ("types" in domain):
+ continue
+ for type in domain["types"]:
+ if type["type"] == "object":
+ type_definitions[domain["domain"] + "." + type["id"]] = create_user_type_definition(domain["domain"], type)
+ elif type["type"] == "array":
+ items_type = type["items"]["type"]
+ type_definitions[domain["domain"] + "." + type["id"]] = wrap_array_definition(type_definitions[items_type])
+ elif type["type"] == domain["domain"] + ".string":
+ type_definitions[domain["domain"] + "." + type["id"]] = create_string_type_definition(domain["domain"])
+ else:
+ type_definitions[domain["domain"] + "." + type["id"]] = create_primitive_type_definition(type["type"])
+
+patch_full_qualified_refs()
+create_type_definitions()
+
+
+def type_definition(name):
+ return type_definitions[name]
+
+
+def resolve_type(property):
+ if "$ref" in property:
+ return type_definitions[property["$ref"]]
+ if property["type"] == "array":
+ return wrap_array_definition(resolve_type(property["items"]))
+ return type_definitions[property["type"]]
+
+
+def join_arrays(dict, keys):
+ result = []
+ for key in keys:
+ if key in dict:
+ result += dict[key]
+ return result
+
+
+if os.path.exists(__file__):
+ current_script_timestamp = os.path.getmtime(__file__)
+else:
+ current_script_timestamp = 0
+
+
+def is_up_to_date(file, template):
+ if not os.path.exists(file):
+ return False
+ timestamp = os.path.getmtime(file)
+ return timestamp > max(os.path.getmtime(module_path + template),
+ current_script_timestamp, json_timestamp)
+
+
+def generate(class_name):
+ h_template_name = "/%s_h.template" % class_name
+ cpp_template_name = "/%s_cpp.template" % class_name
+ h_file_name = output_dirname + "/" + class_name + ".h"
+ cpp_file_name = output_dirname + "/" + class_name + ".cpp"
+
+ if (is_up_to_date(cpp_file_name, cpp_template_name) and
+ is_up_to_date(h_file_name, h_template_name)):
+ return
+
+ template_context = {
+ "class_name": class_name,
+ "api": json_api,
+ "join_arrays": join_arrays,
+ "resolve_type": resolve_type,
+ "type_definition": type_definition
+ }
+ h_template = jinja_env.get_template(h_template_name)
+ cpp_template = jinja_env.get_template(cpp_template_name)
+ h_file = output_file(h_file_name)
+ cpp_file = output_file(cpp_file_name)
+ h_file.write(h_template.render(template_context))
+ cpp_file.write(cpp_template.render(template_context))
+ h_file.close()
+ cpp_file.close()
+
+
+jinja_env = initialize_jinja_env(output_dirname)
+generate("Backend")
+generate("Dispatcher")
+generate("Frontend")
+generate("TypeBuilder")
diff --git a/deps/v8_inspector/platform/inspector_protocol/Collections.h b/deps/v8_inspector/platform/inspector_protocol/Collections.h
new file mode 100644
index 0000000000..960c747bae
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/Collections.h
@@ -0,0 +1,14 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef Collections_h
+#define Collections_h
+
+#if V8_INSPECTOR_USE_STL
+#include "platform/inspector_protocol/CollectionsSTL.h"
+#else
+#include "platform/inspector_protocol/CollectionsWTF.h"
+#endif // V8_INSPECTOR_USE_STL
+
+#endif // !defined(Collections_h)
diff --git a/deps/v8_inspector/platform/inspector_protocol/CollectionsSTL.h b/deps/v8_inspector/platform/inspector_protocol/CollectionsSTL.h
new file mode 100644
index 0000000000..09a1d39971
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/CollectionsSTL.h
@@ -0,0 +1,253 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CollectionsSTL_h
+#define CollectionsSTL_h
+
+#include "platform/inspector_protocol/String16.h"
+#include "wtf/Compiler.h"
+#include "wtf/PtrUtil.h"
+
+#include <algorithm>
+#include <map>
+#include <vector>
+
+namespace blink {
+namespace protocol {
+
+template <typename T>
+class Vector {
+public:
+ Vector() { }
+ Vector(size_t capacity) : m_impl(capacity) { }
+ typedef typename std::vector<T>::iterator iterator;
+ typedef typename std::vector<T>::const_iterator const_iterator;
+
+ iterator begin() { return m_impl.begin(); }
+ iterator end() { return m_impl.end(); }
+ const_iterator begin() const { return m_impl.begin(); }
+ const_iterator end() const { return m_impl.end(); }
+
+ void resize(size_t s) { m_impl.resize(s); }
+ size_t size() const { return m_impl.size(); }
+ bool isEmpty() const { return !m_impl.size(); }
+ T& operator[](size_t i) { return at(i); }
+ const T& operator[](size_t i) const { return at(i); }
+ T& at(size_t i) { return m_impl[i]; }
+ const T& at(size_t i) const { return m_impl.at(i); }
+ T& last() { return m_impl[m_impl.size() - 1]; }
+ const T& last() const { return m_impl[m_impl.size() - 1]; }
+ void append(const T& t) { m_impl.push_back(t); }
+ void prepend(const T& t) { m_impl.insert(m_impl.begin(), t); }
+ void remove(size_t i) { m_impl.erase(m_impl.begin() + i); }
+ void clear() { m_impl.clear(); }
+ void swap(Vector& other) { m_impl.swap(other.m_impl); }
+ void removeLast() { m_impl.pop_back(); }
+
+private:
+ std::vector<T> m_impl;
+};
+
+template <typename T>
+class Vector<std::unique_ptr<T>> {
+public:
+ Vector() { }
+ Vector(size_t capacity) : m_impl(capacity) { }
+ Vector(Vector&& other) { m_impl.swap(other.m_impl); }
+ ~Vector() { clear(); }
+
+ typedef typename std::vector<T*>::iterator iterator;
+ typedef typename std::vector<T*>::const_iterator const_iterator;
+
+ iterator begin() { return m_impl.begin(); }
+ iterator end() { return m_impl.end(); }
+ const_iterator begin() const { return m_impl.begin(); }
+ const_iterator end() const { return m_impl.end(); }
+
+ void resize(size_t s) { m_impl.resize(s); }
+ size_t size() const { return m_impl.size(); }
+ bool isEmpty() const { return !m_impl.size(); }
+ T* operator[](size_t i) { return at(i); }
+ const T* operator[](size_t i) const { return at(i); }
+ T* at(size_t i) { return m_impl[i]; }
+ const T* at(size_t i) const { return m_impl.at(i); }
+ T* last() { return m_impl[m_impl.size() - 1]; }
+ const T* last() const { return m_impl[m_impl.size() - 1]; }
+ void append(std::unique_ptr<T> t) { m_impl.push_back(t.release()); }
+ void prepend(std::unique_ptr<T> t) { m_impl.insert(m_impl.begin(), t.release()); }
+
+ void remove(size_t i)
+ {
+ delete m_impl[i];
+ m_impl.erase(m_impl.begin() + i);
+ }
+
+ void clear()
+ {
+ for (auto t : m_impl)
+ delete t;
+ m_impl.clear();
+ }
+
+ void swap(Vector& other) { m_impl.swap(other.m_impl); }
+ void swap(Vector&& other) { m_impl.swap(other.m_impl); }
+ void removeLast()
+ {
+ delete last();
+ m_impl.pop_back();
+ }
+
+private:
+ Vector(const Vector&) = delete;
+ Vector& operator=(const Vector&) = delete;
+ std::vector<T*> m_impl;
+};
+
+template <typename K, typename V, typename I>
+class HashMapIterator {
+public:
+ HashMapIterator(const I& impl) : m_impl(impl) { }
+ std::pair<K, V*>* get() const { m_pair.first = m_impl->first; m_pair.second = &m_impl->second; return &m_pair; }
+ std::pair<K, V*>& operator*() const { return *get(); }
+ std::pair<K, V*>* operator->() const { return get(); }
+
+ bool operator==(const HashMapIterator<K, V, I>& other) const { return m_impl == other.m_impl; }
+ bool operator!=(const HashMapIterator<K, V, I>& other) const { return m_impl != other.m_impl; }
+
+ HashMapIterator<K, V, I>& operator++() { ++m_impl; return *this; }
+
+private:
+ mutable std::pair<K, V*> m_pair;
+ I m_impl;
+};
+
+template <typename K, typename V, typename I>
+class HashMapIterator<K, std::unique_ptr<V>, I> {
+public:
+ HashMapIterator(const I& impl) : m_impl(impl) { }
+ std::pair<K, V*>* get() const { m_pair.first = m_impl->first; m_pair.second = m_impl->second; return &m_pair; }
+ std::pair<K, V*>& operator*() const { return *get(); }
+ std::pair<K, V*>* operator->() const { return get(); }
+
+ bool operator==(const HashMapIterator<K, std::unique_ptr<V>, I>& other) const { return m_impl == other.m_impl; }
+ bool operator!=(const HashMapIterator<K, std::unique_ptr<V>, I>& other) const { return m_impl != other.m_impl; }
+
+ HashMapIterator<K, std::unique_ptr<V>, I>& operator++() { ++m_impl; return *this; }
+
+private:
+ mutable std::pair<K, V*> m_pair;
+ I m_impl;
+};
+
+template <typename K, typename V>
+class HashMap {
+public:
+ HashMap() { }
+ ~HashMap() { }
+
+ using iterator = HashMapIterator<K, V, typename std::map<K, V>::iterator>;
+ using const_iterator = HashMapIterator<K, const V, typename std::map<K, V>::const_iterator>;
+
+ iterator begin() { return iterator(m_impl.begin()); }
+ iterator end() { return iterator(m_impl.end()); }
+ iterator find(const K& k) { return iterator(m_impl.find(k)); }
+ const_iterator begin() const { return const_iterator(m_impl.begin()); }
+ const_iterator end() const { return const_iterator(m_impl.end()); }
+ const_iterator find(const K& k) const { return const_iterator(m_impl.find(k)); }
+
+ size_t size() const { return m_impl.size(); }
+ bool isEmpty() const { return !m_impl.size(); }
+ bool set(const K& k, const V& v)
+ {
+ bool isNew = m_impl.find(k) == m_impl.end();
+ m_impl[k] = v;
+ return isNew;
+ }
+ bool contains(const K& k) const { return m_impl.find(k) != m_impl.end(); }
+ V get(const K& k) const { auto it = m_impl.find(k); return it == m_impl.end() ? V() : it->second; }
+ void remove(const K& k) { m_impl.erase(k); }
+ void clear() { m_impl.clear(); }
+ V take(const K& k)
+ {
+ V result = m_impl[k];
+ m_impl.erase(k);
+ return result;
+ }
+
+private:
+ std::map<K, V> m_impl;
+};
+
+template <typename K, typename V>
+class HashMap<K, std::unique_ptr<V>> {
+public:
+ HashMap() { }
+ ~HashMap() { clear(); }
+
+ using iterator = HashMapIterator<K, std::unique_ptr<V>, typename std::map<K, V*>::iterator>;
+ using const_iterator = HashMapIterator<K, std::unique_ptr<V>, typename std::map<K, V*>::const_iterator>;
+
+ iterator begin() { return iterator(m_impl.begin()); }
+ iterator end() { return iterator(m_impl.end()); }
+ iterator find(const K& k) { return iterator(m_impl.find(k)); }
+ const_iterator begin() const { return const_iterator(m_impl.begin()); }
+ const_iterator end() const { return const_iterator(m_impl.end()); }
+ const_iterator find(const K& k) const { return const_iterator(m_impl.find(k)); }
+
+ size_t size() const { return m_impl.size(); }
+ bool isEmpty() const { return !m_impl.size(); }
+ bool set(const K& k, std::unique_ptr<V> v)
+ {
+ bool isNew = m_impl.find(k) == m_impl.end();
+ if (!isNew)
+ delete m_impl[k];
+ m_impl[k] = v.release();
+ return isNew;
+ }
+ bool contains(const K& k) const { return m_impl.find(k) != m_impl.end(); }
+ V* get(const K& k) const { auto it = m_impl.find(k); return it == m_impl.end() ? nullptr : it->second; }
+ std::unique_ptr<V> take(const K& k)
+ {
+ if (!contains(k))
+ return nullptr;
+ std::unique_ptr<V> result(m_impl[k]);
+ delete m_impl[k];
+ m_impl.erase(k);
+ return result;
+ }
+ void remove(const K& k)
+ {
+ delete m_impl[k];
+ m_impl.erase(k);
+ }
+
+ void clear()
+ {
+ for (auto pair : m_impl)
+ delete pair.second;
+ m_impl.clear();
+ }
+
+private:
+ std::map<K, V*> m_impl;
+};
+
+template <typename K>
+class HashSet : public protocol::HashMap<K, K> {
+public:
+ void add(const K& k) { this->set(k, k); }
+};
+
+} // namespace platform
+} // namespace blink
+
+// Macro that returns a compile time constant with the length of an array, but gives an error if passed a non-array.
+template<typename T, size_t Size> char (&ArrayLengthHelperFunction(T (&)[Size]))[Size];
+// GCC needs some help to deduce a 0 length array.
+#if COMPILER(GCC)
+template<typename T> char (&ArrayLengthHelperFunction(T (&)[0]))[0];
+#endif
+#define PROTOCOL_ARRAY_LENGTH(array) sizeof(::ArrayLengthHelperFunction(array))
+
+#endif // !defined(CollectionsSTL_h)
diff --git a/deps/v8_inspector/platform/inspector_protocol/CollectionsWTF.h b/deps/v8_inspector/platform/inspector_protocol/CollectionsWTF.h
new file mode 100644
index 0000000000..4642c610b8
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/CollectionsWTF.h
@@ -0,0 +1,193 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CollectionsWTF_h
+#define CollectionsWTF_h
+
+#include "wtf/Assertions.h"
+#include "wtf/HashMap.h"
+#include "wtf/PtrUtil.h"
+#include "wtf/Vector.h"
+#include "wtf/VectorTraits.h"
+
+namespace blink {
+namespace protocol {
+
+template <typename T>
+class Vector {
+public:
+ Vector() { }
+ Vector(size_t capacity) : m_impl(capacity) { }
+ typedef T* iterator;
+ typedef const T* const_iterator;
+
+ iterator begin() { return m_impl.begin(); }
+ iterator end() { return m_impl.end(); }
+ const_iterator begin() const { return m_impl.begin(); }
+ const_iterator end() const { return m_impl.end(); }
+
+ void resize(size_t s) { m_impl.resize(s); }
+ size_t size() const { return m_impl.size(); }
+ bool isEmpty() const { return m_impl.isEmpty(); }
+ T& operator[](size_t i) { return at(i); }
+ const T& operator[](size_t i) const { return at(i); }
+ T& at(size_t i) { return m_impl.at(i); }
+ const T& at(size_t i) const { return m_impl.at(i); }
+ T& last() { return m_impl.last(); }
+ const T& last() const { return m_impl.last(); }
+ void append(const T& t) { m_impl.append(t); }
+ void prepend(const T& t) { m_impl.prepend(t); }
+ void remove(size_t i) { m_impl.remove(i); }
+ void clear() { m_impl.clear(); }
+ void swap(Vector<T>& other) { m_impl.swap(other.m_impl); }
+ void removeLast() { m_impl.removeLast(); }
+
+private:
+ WTF::Vector<T> m_impl;
+};
+
+template <typename T>
+class Vector<std::unique_ptr<T>> {
+ WTF_MAKE_NONCOPYABLE(Vector);
+public:
+ Vector() { }
+ Vector(size_t capacity) : m_impl(capacity) { }
+ Vector(Vector<std::unique_ptr<T>>&& other) : m_impl(std::move(other.m_impl)) { }
+ ~Vector() { }
+
+ typedef std::unique_ptr<T>* iterator;
+ typedef const std::unique_ptr<T>* const_iterator;
+
+ iterator begin() { return m_impl.begin(); }
+ iterator end() { return m_impl.end(); }
+ const_iterator begin() const { return m_impl.begin(); }
+ const_iterator end() const { return m_impl.end(); }
+
+ void resize(size_t s) { m_impl.resize(s); }
+ size_t size() const { return m_impl.size(); }
+ bool isEmpty() const { return m_impl.isEmpty(); }
+ std::unique_ptr<T>& operator[](size_t i) { return m_impl.at(i); }
+ const std::unique_ptr<T>& operator[](size_t i) const { return m_impl.at(i); }
+ std::unique_ptr<T>& at(size_t i) { return m_impl.at(i); }
+ const std::unique_ptr<T>& at(size_t i) const { return m_impl.at(i); }
+ std::unique_ptr<T>& last() { return m_impl.last(); }
+ const std::unique_ptr<T>& last() const { return m_impl.last(); }
+ void append(std::unique_ptr<T> t) { m_impl.append(std::move(t)); }
+ void prepend(std::unique_ptr<T> t) { m_impl.prepend(std::move(t)); }
+ void remove(size_t i) { m_impl.remove(i); }
+ void clear() { m_impl.clear(); }
+ void swap(Vector<std::unique_ptr<T>>& other) { m_impl.swap(other.m_impl); }
+ void swap(Vector<std::unique_ptr<T>>&& other) { m_impl.swap(other.m_impl); }
+ void removeLast() { m_impl.removeLast(); }
+
+private:
+ WTF::Vector<std::unique_ptr<T>> m_impl;
+};
+
+template <typename K, typename V, typename I>
+class HashMapIterator {
+ STACK_ALLOCATED();
+public:
+ HashMapIterator(const I& impl) : m_impl(impl) { }
+ std::pair<K, V*>* get() const { m_pair = std::make_pair(m_impl->key, &m_impl->value); return &m_pair; }
+ std::pair<K, V*>& operator*() const { return *get(); }
+ std::pair<K, V*>* operator->() const { return get(); }
+
+ bool operator==(const HashMapIterator<K, V, I>& other) const { return m_impl == other.m_impl; }
+ bool operator!=(const HashMapIterator<K, V, I>& other) const { return m_impl != other.m_impl; }
+
+ HashMapIterator<K, V, I>& operator++() { ++m_impl; return *this; }
+
+private:
+ mutable std::pair<K, V*> m_pair;
+ I m_impl;
+};
+
+template <typename K, typename V, typename I>
+class HashMapIterator<K, std::unique_ptr<V>, I> {
+ STACK_ALLOCATED();
+public:
+ HashMapIterator(const I& impl) : m_impl(impl) { }
+ std::pair<K, V*>* get() const { m_pair = std::make_pair(m_impl->key, m_impl->value.get()); return &m_pair; }
+ std::pair<K, V*>& operator*() const { return *get(); }
+ std::pair<K, V*>* operator->() const { return get(); }
+
+ bool operator==(const HashMapIterator<K, std::unique_ptr<V>, I>& other) const { return m_impl == other.m_impl; }
+ bool operator!=(const HashMapIterator<K, std::unique_ptr<V>, I>& other) const { return m_impl != other.m_impl; }
+
+ HashMapIterator<K, std::unique_ptr<V>, I>& operator++() { ++m_impl; return *this; }
+
+private:
+ mutable std::pair<K, V*> m_pair;
+ I m_impl;
+};
+
+template <typename K, typename V>
+class HashMap {
+public:
+ HashMap() { }
+ ~HashMap() { }
+
+ using iterator = HashMapIterator<K, V, typename WTF::HashMap<K, V>::iterator>;
+ using const_iterator = HashMapIterator<K, const V, typename WTF::HashMap<K, V>::const_iterator>;
+
+ iterator begin() { return iterator(m_impl.begin()); }
+ iterator end() { return iterator(m_impl.end()); }
+ iterator find(const K& k) { return iterator(m_impl.find(k)); }
+ const_iterator begin() const { return const_iterator(m_impl.begin()); }
+ const_iterator end() const { return const_iterator(m_impl.end()); }
+ const_iterator find(const K& k) const { return const_iterator(m_impl.find(k)); }
+
+ size_t size() const { return m_impl.size(); }
+ bool isEmpty() const { return m_impl.isEmpty(); }
+ bool set(const K& k, const V& v) { return m_impl.set(k, v).isNewEntry; }
+ bool contains(const K& k) const { return m_impl.contains(k); }
+ V get(const K& k) const { return m_impl.get(k); }
+ void remove(const K& k) { m_impl.remove(k); }
+ void clear() { m_impl.clear(); }
+ V take(const K& k) { return m_impl.take(k); }
+
+private:
+ WTF::HashMap<K, V> m_impl;
+};
+
+template <typename K, typename V>
+class HashMap<K, std::unique_ptr<V>> {
+public:
+ HashMap() { }
+ ~HashMap() { }
+
+ using iterator = HashMapIterator<K, std::unique_ptr<V>, typename WTF::HashMap<K, std::unique_ptr<V>>::iterator>;
+ using const_iterator = HashMapIterator<K, std::unique_ptr<V>, typename WTF::HashMap<K, std::unique_ptr<V>>::const_iterator>;
+
+ iterator begin() { return iterator(m_impl.begin()); }
+ iterator end() { return iterator(m_impl.end()); }
+ iterator find(const K& k) { return iterator(m_impl.find(k)); }
+ const_iterator begin() const { return const_iterator(m_impl.begin()); }
+ const_iterator end() const { return const_iterator(m_impl.end()); }
+ const_iterator find(const K& k) const { return const_iterator(m_impl.find(k)); }
+
+ size_t size() const { return m_impl.size(); }
+ bool isEmpty() const { return m_impl.isEmpty(); }
+ bool set(const K& k, std::unique_ptr<V> v) { return m_impl.set(k, std::move(v)).isNewEntry; }
+ bool contains(const K& k) const { return m_impl.contains(k); }
+ V* get(const K& k) const { return m_impl.get(k); }
+ std::unique_ptr<V> take(const K& k) { return m_impl.take(k); }
+ void remove(const K& k) { m_impl.remove(k); }
+ void clear() { m_impl.clear(); }
+
+private:
+ WTF::HashMap<K, std::unique_ptr<V>> m_impl;
+};
+
+template <typename K>
+class HashSet : public protocol::HashMap<K, K> {
+public:
+ void add(const K& k) { this->set(k, k); }
+};
+
+} // namespace platform
+} // namespace blink
+
+#endif // !defined(CollectionsWTF_h)
diff --git a/deps/v8_inspector/platform/inspector_protocol/Dispatcher_cpp.template b/deps/v8_inspector/platform/inspector_protocol/Dispatcher_cpp.template
new file mode 100644
index 0000000000..bb7c17b5ee
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/Dispatcher_cpp.template
@@ -0,0 +1,365 @@
+// This file is generated
+
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/inspector_protocol/{{class_name}}.h"
+
+#include "platform/inspector_protocol/Collections.h"
+#include "platform/inspector_protocol/FrontendChannel.h"
+#include "platform/inspector_protocol/Parser.h"
+
+namespace blink {
+namespace protocol {
+
+using protocol::Maybe;
+
+class DispatcherImpl;
+
+class DispatcherImplWeakPtr {
+public:
+ DispatcherImplWeakPtr(DispatcherImpl* dispatcher) : m_dispatcher(dispatcher) { }
+ ~DispatcherImplWeakPtr();
+ DispatcherImpl* get() { return m_dispatcher; }
+ void dispose() { m_dispatcher = nullptr; }
+private:
+ DispatcherImpl* m_dispatcher;
+};
+
+class DispatcherImpl : public Dispatcher {
+public:
+ DispatcherImpl(FrontendChannel* frontendChannel)
+ : m_frontendChannel(frontendChannel)
+{% for domain in api.domains %}
+ , m_{{domain.domain | lower}}Agent(0)
+{% endfor %}
+ {
+{% for domain in api.domains %}
+ {% for command in domain.commands %}
+ {% if "redirect" in command %}{% continue %}{% endif %}
+ {% if "handlers" in command and not ("renderer" in command["handlers"]) %}{% continue %}{% endif %}
+ m_dispatchMap.set("{{domain.domain}}.{{command.name}}", &DispatcherImpl::{{domain.domain}}_{{command.name}});
+ {% endfor %}
+{% endfor %}
+
+ // Initialize common errors.
+ m_commonErrors.resize(LastEntry);
+ m_commonErrors[ParseError] = -32700;
+ m_commonErrors[InvalidRequest] = -32600;
+ m_commonErrors[MethodNotFound] = -32601;
+ m_commonErrors[InvalidParams] = -32602;
+ m_commonErrors[InternalError] = -32603;
+ m_commonErrors[ServerError] = -32000;
+ }
+
+ ~DispatcherImpl() { clearFrontend(); }
+
+ virtual void clearFrontend()
+ {
+ m_frontendChannel = nullptr;
+ for (auto& weak : m_weakPtrs)
+ weak.first->dispose();
+ m_weakPtrs.clear();
+ }
+
+ std::unique_ptr<DispatcherImplWeakPtr> weakPtr()
+ {
+ std::unique_ptr<DispatcherImplWeakPtr> weak(new DispatcherImplWeakPtr(this));
+ m_weakPtrs.add(weak.get());
+ return weak;
+ }
+
+ virtual void dispatch(int sessionId, const String16& message);
+ virtual void reportProtocolError(int sessionId, int callId, CommonErrorCode, const String16& errorMessage, ErrorSupport* errors) const;
+ using Dispatcher::reportProtocolError;
+
+ void sendResponse(int sessionId, int callId, const ErrorString& invocationError, ErrorSupport* errors, std::unique_ptr<protocol::DictionaryValue> result);
+
+{% for domain in api.domains %}
+ virtual void registerAgent(blink::protocol::Backend::{{domain.domain}}* agent) { DCHECK(!m_{{domain.domain | lower}}Agent); m_{{domain.domain | lower}}Agent = agent; }
+{% endfor %}
+
+private:
+ friend class DispatcherCallbackBase;
+ friend class DispatcherImplWeakPtr;
+ using CallHandler = void (DispatcherImpl::*)(int sessionId, int callId, std::unique_ptr<DictionaryValue> messageObject, ErrorSupport* errors);
+ using DispatchMap = protocol::HashMap<String16, CallHandler>;
+
+{% for domain in api.domains %}
+ {% for command in domain.commands %}
+ {% if "redirect" in command %}{% continue %}{% endif %}
+ {% if "handlers" in command and not ("renderer" in command["handlers"]) %}{% continue %}{% endif %}
+ void {{domain.domain}}_{{command.name}}(int sessionId, int callId, std::unique_ptr<DictionaryValue> requestMessageObject, ErrorSupport*);
+ {% endfor %}
+{% endfor %}
+
+ FrontendChannel* m_frontendChannel;
+
+{% for domain in api.domains %}
+ Backend::{{domain.domain}}* m_{{domain.domain | lower}}Agent;
+{% endfor %}
+
+ void sendResponse(int sessionId, int callId, ErrorString invocationError, std::unique_ptr<protocol::DictionaryValue> result)
+ {
+ sendResponse(sessionId, callId, invocationError, nullptr, std::move(result));
+ }
+
+ void sendResponse(int sessionId, int callId, ErrorString invocationError)
+ {
+ sendResponse(sessionId, callId, invocationError, nullptr, DictionaryValue::create());
+ }
+
+ static const char kInvalidRequest[];
+
+ DispatchMap m_dispatchMap;
+ protocol::Vector<int> m_commonErrors;
+ protocol::HashSet<DispatcherImplWeakPtr*> m_weakPtrs;
+};
+
+class PLATFORM_EXPORT DispatcherCallbackBase : public protocol::Backend::CallbackBase {
+public:
+ DispatcherCallbackBase(std::unique_ptr<DispatcherImplWeakPtr> backendImpl, int sessionId, int id)
+ : m_backendImpl(std::move(backendImpl)), m_sessionId(sessionId), m_id(id) { }
+ virtual ~DispatcherCallbackBase() { }
+ void dispose() { m_backendImpl = nullptr; }
+
+protected:
+ void sendIfActive(std::unique_ptr<protocol::DictionaryValue> partialMessage, const ErrorString& invocationError)
+ {
+ if (!m_backendImpl->get())
+ return;
+ m_backendImpl->get()->sendResponse(m_sessionId, m_id, invocationError, nullptr, std::move(partialMessage));
+ m_backendImpl = nullptr;
+ }
+
+private:
+ std::unique_ptr<DispatcherImplWeakPtr> m_backendImpl;
+ int m_sessionId;
+ int m_id;
+};
+
+DispatcherImplWeakPtr::~DispatcherImplWeakPtr()
+{
+ if (m_dispatcher)
+ m_dispatcher->m_weakPtrs.remove(this);
+}
+
+const char DispatcherImpl::kInvalidRequest[] = "Invalid request";
+
+{% for domain in api.domains %}
+ {% for command in domain.commands %}
+ {% if "redirect" in command %}{% continue %}{% endif %}
+ {% if "handlers" in command and not ("renderer" in command["handlers"]) %}{% continue %}{% endif %}
+
+ {% if "async" in command %}
+
+class PLATFORM_EXPORT {{domain.domain}}{{command.name | to_title_case}}Callback : public Backend::{{domain.domain}}::{{command.name | to_title_case}}Callback, public DispatcherCallbackBase {
+public:
+ {{domain.domain}}{{command.name | to_title_case}}Callback(std::unique_ptr<DispatcherImplWeakPtr> backendImpl, int sessionId, int id)
+ : DispatcherCallbackBase(std::move(backendImpl), sessionId, id) { }
+
+ void sendSuccess(
+ {%- for parameter in command.returns -%}
+ {%- if "optional" in parameter -%}
+ const Maybe<{{resolve_type(parameter).raw_type}}>& {{parameter.name}}
+ {%- else -%}
+ {{resolve_type(parameter).pass_type}} {{parameter.name}}
+ {%- endif -%}
+ {%- if not loop.last -%}, {% endif -%}
+ {%- endfor -%}) override
+ {
+ std::unique_ptr<protocol::DictionaryValue> resultObject = DictionaryValue::create();
+ {% for parameter in command.returns %}
+ {% if "optional" in parameter %}
+ if ({{parameter.name}}.isJust())
+ resultObject->setValue("{{parameter.name}}", toValue({{parameter.name}}.fromJust()));
+ {% else %}
+ resultObject->setValue("{{parameter.name}}", toValue({{resolve_type(parameter).to_raw_type % parameter.name}}));
+ {% endif %}
+ {% endfor %}
+ sendIfActive(std::move(resultObject), ErrorString());
+ }
+
+ void sendFailure(const ErrorString& error) override
+ {
+ DCHECK(error.length());
+ sendIfActive(nullptr, error);
+ }
+};
+ {% endif %}
+
+void DispatcherImpl::{{domain.domain}}_{{command.name}}(int sessionId, int callId, std::unique_ptr<DictionaryValue> requestMessageObject, ErrorSupport* errors)
+{
+ if (!m_{{domain.domain | lower}}Agent)
+ errors->addError("{{domain.domain}} handler is not available.");
+
+ if (errors->hasErrors()) {
+ reportProtocolError(sessionId, callId, InvalidParams, kInvalidRequest, errors);
+ return;
+ }
+ {% if "parameters" in command %}
+
+ // Prepare input parameters.
+ protocol::DictionaryValue* object = DictionaryValue::cast(requestMessageObject->get("params"));
+ errors->push();
+ {% for property in command.parameters %}
+ protocol::Value* {{property.name}}Value = object ? object->get("{{property.name}}") : nullptr;
+ {% if property.optional %}
+ Maybe<{{resolve_type(property).raw_type}}> in_{{property.name}};
+ if ({{property.name}}Value) {
+ errors->setName("{{property.name}}");
+ in_{{property.name}} = FromValue<{{resolve_type(property).raw_type}}>::parse({{property.name}}Value, errors);
+ }
+ {% else %}
+ errors->setName("{{property.name}}");
+ {{resolve_type(property).type}} in_{{property.name}} = FromValue<{{resolve_type(property).raw_type}}>::parse({{property.name}}Value, errors);
+ {% endif %}
+ {% endfor %}
+ errors->pop();
+ if (errors->hasErrors()) {
+ reportProtocolError(sessionId, callId, InvalidParams, kInvalidRequest, errors);
+ return;
+ }
+ {% endif %}
+
+ {% if "async" in command %}
+ std::unique_ptr<{{domain.domain}}{{command.name | to_title_case}}Callback> callback(new {{domain.domain}}{{command.name | to_title_case}}Callback(weakPtr(), sessionId, callId));
+ {% elif "returns" in command %}
+ // Declare output parameters.
+ std::unique_ptr<protocol::DictionaryValue> result = DictionaryValue::create();
+ {% for property in command.returns %}
+ {% if "optional" in property %}
+ Maybe<{{resolve_type(property).raw_type}}> out_{{property.name}};
+ {% else %}
+ {{resolve_type(property).type}} out_{{property.name}};
+ {% endif %}
+ {% endfor %}
+ {% endif %}
+
+ std::unique_ptr<DispatcherImplWeakPtr> weak = weakPtr();
+ ErrorString error;
+ m_{{domain.domain | lower}}Agent->{{command.name}}(&error
+ {%- for property in command.parameters -%}
+ {%- if "optional" in property -%}
+ , in_{{property.name}}
+ {%- else -%}
+ , {{resolve_type(property).to_pass_type % ("in_" + property.name)}}
+ {%- endif -%}
+ {%- endfor %}
+ {%- if "async" in command -%}
+ , std::move(callback)
+ {%- elif "returns" in command %}
+ {%- for property in command.returns -%}
+ , &out_{{property.name}}
+ {%- endfor %}
+ {% endif %});
+ {% if "returns" in command and not("async" in command) %}
+ if (!error.length()) {
+ {% for parameter in command.returns %}
+ {% if "optional" in parameter %}
+ if (out_{{parameter.name}}.isJust())
+ result->setValue("{{parameter.name}}", toValue(out_{{parameter.name}}.fromJust()));
+ {% else %}
+ result->setValue("{{parameter.name}}", toValue({{resolve_type(parameter).to_raw_type % ("out_" + parameter.name)}}));
+ {% endif %}
+ {% endfor %}
+ }
+ if (weak->get())
+ weak->get()->sendResponse(sessionId, callId, error, std::move(result));
+ {% elif not("async" in command) %}
+ if (weak->get())
+ weak->get()->sendResponse(sessionId, callId, error);
+ {% endif %}
+}
+ {% endfor %}
+{% endfor %}
+
+std::unique_ptr<Dispatcher> Dispatcher::create(FrontendChannel* frontendChannel)
+{
+ return wrapUnique(new DispatcherImpl(frontendChannel));
+}
+
+void DispatcherImpl::dispatch(int sessionId, const String16& message)
+{
+ int callId = 0;
+ std::unique_ptr<protocol::Value> parsedMessage = parseJSON(message);
+ DCHECK(parsedMessage);
+ std::unique_ptr<protocol::DictionaryValue> messageObject = DictionaryValue::cast(std::move(parsedMessage));
+ DCHECK(messageObject);
+
+ protocol::Value* callIdValue = messageObject->get("id");
+ bool success = callIdValue->asNumber(&callId);
+ DCHECK(success);
+
+ protocol::Value* methodValue = messageObject->get("method");
+ String16 method;
+ success = methodValue && methodValue->asString(&method);
+ DCHECK(success);
+
+ protocol::HashMap<String16, CallHandler>::iterator it = m_dispatchMap.find(method);
+ if (it == m_dispatchMap.end()) {
+ reportProtocolError(sessionId, callId, MethodNotFound, "'" + method + "' wasn't found");
+ return;
+ }
+
+ protocol::ErrorSupport errors;
+ ((*this).*(*it->second))(sessionId, callId, std::move(messageObject), &errors);
+}
+
+void DispatcherImpl::sendResponse(int sessionId, int callId, const ErrorString& invocationError, ErrorSupport* errors, std::unique_ptr<protocol::DictionaryValue> result)
+{
+ if (invocationError.length() || (errors && errors->hasErrors())) {
+ reportProtocolError(sessionId, callId, ServerError, invocationError, errors);
+ return;
+ }
+
+ std::unique_ptr<protocol::DictionaryValue> responseMessage = DictionaryValue::create();
+ responseMessage->setNumber("id", callId);
+ responseMessage->setObject("result", std::move(result));
+ if (m_frontendChannel)
+ m_frontendChannel->sendProtocolResponse(sessionId, callId, std::move(responseMessage));
+}
+
+void Dispatcher::reportProtocolError(int sessionId, int callId, CommonErrorCode code, const String16& errorMessage) const
+{
+ ErrorSupport errors;
+ reportProtocolError(sessionId, callId, code, errorMessage, &errors);
+}
+
+void DispatcherImpl::reportProtocolError(int sessionId, int callId, CommonErrorCode code, const String16& errorMessage, ErrorSupport* errors) const
+{
+ DCHECK(code >=0);
+ DCHECK((unsigned)code < m_commonErrors.size());
+ DCHECK(m_commonErrors[code]);
+ std::unique_ptr<protocol::DictionaryValue> error = DictionaryValue::create();
+ error->setNumber("code", m_commonErrors[code]);
+ error->setString("message", errorMessage);
+ DCHECK(error);
+ if (errors && errors->hasErrors())
+ error->setString("data", errors->errors());
+ std::unique_ptr<protocol::DictionaryValue> message = DictionaryValue::create();
+ message->setObject("error", std::move(error));
+ message->setNumber("id", callId);
+ if (m_frontendChannel)
+ m_frontendChannel->sendProtocolResponse(sessionId, callId, std::move(message));
+}
+
+bool Dispatcher::getCommandName(const String16& message, String16* result)
+{
+ std::unique_ptr<protocol::Value> value = parseJSON(message);
+ if (!value)
+ return false;
+
+ protocol::DictionaryValue* object = DictionaryValue::cast(value.get());
+ if (!object)
+ return false;
+
+ if (!object->getString("method", result))
+ return false;
+
+ return true;
+}
+
+} // namespace protocol
+} // namespace blink
diff --git a/deps/v8_inspector/platform/inspector_protocol/Dispatcher_h.template b/deps/v8_inspector/platform/inspector_protocol/Dispatcher_h.template
new file mode 100644
index 0000000000..6a809bbff0
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/Dispatcher_h.template
@@ -0,0 +1,65 @@
+// This file is generated
+
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef {{class_name}}_h
+#define {{class_name}}_h
+
+#include "platform/inspector_protocol/Backend.h"
+#include "platform/inspector_protocol/TypeBuilder.h"
+
+namespace blink {
+namespace protocol {
+
+class FrontendChannel;
+class DispatcherImplWeakPtr;
+
+class PLATFORM_EXPORT Dispatcher {
+public:
+ static std::unique_ptr<Dispatcher> create(FrontendChannel* frontendChannel);
+ virtual ~Dispatcher() { }
+
+ class PLATFORM_EXPORT CallbackBase {
+ public:
+ CallbackBase(std::unique_ptr<DispatcherImplWeakPtr> backendImpl, int sessionId, int id);
+ virtual ~CallbackBase();
+ void sendFailure(const ErrorString&);
+ void dispose();
+
+ protected:
+ void sendIfActive(std::unique_ptr<protocol::DictionaryValue> partialMessage, const ErrorString& invocationError);
+
+ private:
+ std::unique_ptr<DispatcherImplWeakPtr> m_backendImpl;
+ int m_sessionId;
+ int m_id;
+ };
+
+{% for domain in api.domains %}
+ virtual void registerAgent(blink::protocol::Backend::{{domain.domain}}*) = 0;
+{% endfor %}
+
+ virtual void clearFrontend() = 0;
+
+ enum CommonErrorCode {
+ ParseError = 0,
+ InvalidRequest,
+ MethodNotFound,
+ InvalidParams,
+ InternalError,
+ ServerError,
+ LastEntry,
+ };
+
+ void reportProtocolError(int sessionId, int callId, CommonErrorCode, const String16& errorMessage) const;
+ virtual void reportProtocolError(int sessionId, int callId, CommonErrorCode, const String16& errorMessage, ErrorSupport*) const = 0;
+ virtual void dispatch(int sessionId, const String16& message) = 0;
+ static bool getCommandName(const String16& message, String16* result);
+};
+
+} // namespace protocol
+} // namespace blink
+
+#endif // !defined({{class_name}}_h)
diff --git a/deps/v8_inspector/platform/inspector_protocol/ErrorSupport.cpp b/deps/v8_inspector/platform/inspector_protocol/ErrorSupport.cpp
new file mode 100644
index 0000000000..87603e980b
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/ErrorSupport.cpp
@@ -0,0 +1,71 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/inspector_protocol/ErrorSupport.h"
+
+#include "platform/inspector_protocol/String16.h"
+#include "wtf/Assertions.h"
+
+namespace blink {
+namespace protocol {
+
+ErrorSupport::ErrorSupport() : m_errorString(nullptr) { }
+ErrorSupport::ErrorSupport(String16* errorString) : m_errorString(errorString) { }
+ErrorSupport::~ErrorSupport()
+{
+ if (m_errorString && hasErrors()) {
+ String16Builder builder;
+ builder.append("Internal error(s): ");
+ builder.append(errors());
+ *m_errorString = builder.toString();
+ }
+}
+
+void ErrorSupport::setName(const String16& name)
+{
+ DCHECK(m_path.size());
+ m_path[m_path.size() - 1] = name;
+}
+
+void ErrorSupport::push()
+{
+ m_path.append(String16());
+}
+
+void ErrorSupport::pop()
+{
+ m_path.removeLast();
+}
+
+void ErrorSupport::addError(const String16& error)
+{
+ String16Builder builder;
+ for (size_t i = 0; i < m_path.size(); ++i) {
+ if (i)
+ builder.append(".");
+ builder.append(m_path[i]);
+ }
+ builder.append(": ");
+ builder.append(error);
+ m_errors.append(builder.toString());
+}
+
+bool ErrorSupport::hasErrors()
+{
+ return m_errors.size();
+}
+
+String16 ErrorSupport::errors()
+{
+ String16Builder builder;
+ for (size_t i = 0; i < m_errors.size(); ++i) {
+ if (i)
+ builder.append("; ");
+ builder.append(m_errors[i]);
+ }
+ return builder.toString();
+}
+
+} // namespace protocol
+} // namespace blink
diff --git a/deps/v8_inspector/platform/inspector_protocol/ErrorSupport.h b/deps/v8_inspector/platform/inspector_protocol/ErrorSupport.h
new file mode 100644
index 0000000000..98a3340f2c
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/ErrorSupport.h
@@ -0,0 +1,37 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ErrorSupport_h
+#define ErrorSupport_h
+
+#include "platform/PlatformExport.h"
+#include "platform/inspector_protocol/Collections.h"
+#include "platform/inspector_protocol/String16.h"
+
+namespace blink {
+namespace protocol {
+
+class PLATFORM_EXPORT ErrorSupport {
+public:
+ ErrorSupport();
+ ErrorSupport(String16* errorString);
+ ~ErrorSupport();
+
+ void push();
+ void setName(const String16&);
+ void pop();
+ void addError(const String16&);
+ bool hasErrors();
+ String16 errors();
+
+private:
+ protocol::Vector<String16> m_path;
+ protocol::Vector<String16> m_errors;
+ String16* m_errorString;
+};
+
+} // namespace platform
+} // namespace blink
+
+#endif // !defined(ErrorSupport_h)
diff --git a/deps/v8_inspector/platform/inspector_protocol/FrontendChannel.h b/deps/v8_inspector/platform/inspector_protocol/FrontendChannel.h
new file mode 100644
index 0000000000..27ba557c4a
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/FrontendChannel.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FrontendChannel_h
+#define FrontendChannel_h
+
+#include "platform/inspector_protocol/Values.h"
+
+namespace blink {
+namespace protocol {
+
+class FrontendChannel {
+public:
+ virtual ~FrontendChannel() { }
+ virtual void sendProtocolResponse(int sessionId, int callId, std::unique_ptr<protocol::DictionaryValue> message) = 0;
+ virtual void sendProtocolNotification(std::unique_ptr<protocol::DictionaryValue> message) = 0;
+ virtual void flush() = 0;
+};
+
+} // namespace protocol
+} // namespace blink
+
+#endif // !defined(FrontendChannel_h)
diff --git a/deps/v8_inspector/platform/inspector_protocol/Frontend_cpp.template b/deps/v8_inspector/platform/inspector_protocol/Frontend_cpp.template
new file mode 100644
index 0000000000..137dc8e2b1
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/Frontend_cpp.template
@@ -0,0 +1,53 @@
+// This file is generated
+
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/inspector_protocol/{{class_name}}.h"
+
+#include "platform/inspector_protocol/String16.h"
+
+namespace blink {
+namespace protocol {
+
+Frontend::Frontend(FrontendChannel* frontendChannel)
+ : m_frontendChannel(frontendChannel)
+{% for domain in api.domains %}
+ , m_{{domain.domain | lower}}(frontendChannel)
+{% endfor %}
+{
+}
+
+{% for domain in api.domains %}
+ {% for event in domain.events %}
+ {% if "handlers" in event and not ("renderer" in event["handlers"]) %}{% continue %}{% endif %}
+void Frontend::{{domain.domain}}::{{event.name}}(
+ {%- for parameter in event.parameters %}
+ {% if "optional" in parameter -%}
+ const Maybe<{{resolve_type(parameter).raw_type}}>&
+ {%- else -%}
+ {{resolve_type(parameter).pass_type}}
+ {%- endif %} {{parameter.name}}{%- if not loop.last -%}, {% endif -%}
+ {% endfor -%})
+{
+ std::unique_ptr<protocol::DictionaryValue> jsonMessage = DictionaryValue::create();
+ jsonMessage->setString("method", "{{domain.domain}}.{{event.name}}");
+ std::unique_ptr<protocol::DictionaryValue> paramsObject = DictionaryValue::create();
+ {% for parameter in event.parameters %}
+ {% if "optional" in parameter %}
+ if ({{parameter.name}}.isJust())
+ paramsObject->setValue("{{parameter.name}}", toValue({{parameter.name}}.fromJust()));
+ {% else %}
+ paramsObject->setValue("{{parameter.name}}", toValue({{resolve_type(parameter).to_raw_type % parameter.name}}));
+ {% endif %}
+ {% endfor %}
+ jsonMessage->setObject("params", std::move(paramsObject));
+ if (m_frontendChannel)
+ m_frontendChannel->sendProtocolNotification(std::move(jsonMessage));
+}
+ {% endfor %}
+{% endfor %}
+
+} // namespace protocol
+} // namespace blink
diff --git a/deps/v8_inspector/platform/inspector_protocol/Frontend_h.template b/deps/v8_inspector/platform/inspector_protocol/Frontend_h.template
new file mode 100644
index 0000000000..79cc64b48e
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/Frontend_h.template
@@ -0,0 +1,57 @@
+// This file is generated
+
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef {{class_name}}_h
+#define {{class_name}}_h
+
+
+#include "platform/inspector_protocol/FrontendChannel.h"
+#include "platform/inspector_protocol/TypeBuilder.h"
+
+namespace blink {
+namespace protocol {
+
+class PLATFORM_EXPORT Frontend {
+public:
+ Frontend(FrontendChannel*);
+ FrontendChannel* channel() { return m_frontendChannel; }
+
+{% for domain in api.domains %}
+
+ class PLATFORM_EXPORT {{domain.domain}} {
+ public:
+ static {{domain.domain}}* from(Frontend* frontend) { return &(frontend->m_{{domain.domain | lower}}) ;}
+ {{domain.domain}}(FrontendChannel* frontendChannel) : m_frontendChannel(frontendChannel) { }
+ {% for event in domain.events %}
+ {% if "handlers" in event and not ("renderer" in event["handlers"]) %}{% continue %}{% endif %}
+ void {{event.name}}(
+ {%- for parameter in event.parameters -%}
+ {%- if "optional" in parameter -%}
+ const Maybe<{{resolve_type(parameter).raw_type}}>& {{parameter.name}} = Maybe<{{resolve_type(parameter).raw_type}}>()
+ {%- else -%}
+ {{resolve_type(parameter).pass_type}} {{parameter.name}}
+ {%- endif -%}{%- if not loop.last -%}, {% endif -%}
+ {%- endfor -%}
+ );
+ {% endfor %}
+
+ void flush() { m_frontendChannel->flush(); }
+ private:
+ FrontendChannel* m_frontendChannel;
+ };
+{% endfor %}
+
+private:
+ FrontendChannel* m_frontendChannel;
+{% for domain in api.domains %}
+ {{domain.domain}} m_{{domain.domain | lower}};
+{% endfor %}
+};
+
+} // namespace protocol
+} // namespace blink
+
+#endif // !defined({{class_name}}_h)
diff --git a/deps/v8_inspector/platform/inspector_protocol/Maybe.h b/deps/v8_inspector/platform/inspector_protocol/Maybe.h
new file mode 100644
index 0000000000..652d5aa502
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/Maybe.h
@@ -0,0 +1,89 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef Maybe_h
+#define Maybe_h
+
+#include "platform/PlatformExport.h"
+#include "wtf/Assertions.h"
+
+namespace blink {
+namespace protocol {
+
+class String16;
+
+template<typename T>
+class Maybe {
+public:
+ Maybe() { }
+ Maybe(std::unique_ptr<T> value) : m_value(std::move(value)) { }
+ void operator=(std::unique_ptr<T> value) { m_value = std::move(value); }
+ T* fromJust() const { DCHECK(m_value); return m_value.get(); }
+ T* fromMaybe(T* defaultValue) const { return m_value ? m_value.get() : defaultValue; }
+ bool isJust() const { return !!m_value; }
+ std::unique_ptr<T> takeJust() { DCHECK(m_value); return m_value.release(); }
+private:
+ std::unique_ptr<T> m_value;
+};
+
+template<typename T>
+class MaybeBase {
+public:
+ MaybeBase() : m_isJust(false) { }
+ MaybeBase(T value) : m_isJust(true), m_value(value) { }
+ void operator=(T value) { m_value = value; m_isJust = true; }
+ T fromJust() const { DCHECK(m_isJust); return m_value; }
+ T fromMaybe(const T& defaultValue) const { return m_isJust ? m_value : defaultValue; }
+ bool isJust() const { return m_isJust; }
+ T takeJust() { DCHECK(m_isJust); return m_value; }
+
+protected:
+ bool m_isJust;
+ T m_value;
+};
+
+template<>
+class Maybe<bool> : public MaybeBase<bool> {
+public:
+ Maybe() { }
+ Maybe(bool value) : MaybeBase(value) { }
+ using MaybeBase::operator=;
+};
+
+template<>
+class Maybe<int> : public MaybeBase<int> {
+public:
+ Maybe() { }
+ Maybe(int value) : MaybeBase(value) { }
+ using MaybeBase::operator=;
+};
+
+template<>
+class Maybe<double> : public MaybeBase<double> {
+public:
+ Maybe() { }
+ Maybe(double value) : MaybeBase(value) { }
+ using MaybeBase::operator=;
+};
+
+template<>
+class Maybe<String> : public MaybeBase<String> {
+public:
+ Maybe() { }
+ Maybe(const String& value) : MaybeBase(value) { }
+ using MaybeBase::operator=;
+};
+
+template<>
+class Maybe<String16> : public MaybeBase<String16> {
+public:
+ Maybe() { }
+ Maybe(const String16& value) : MaybeBase(value) { }
+ using MaybeBase::operator=;
+};
+
+} // namespace platform
+} // namespace blink
+
+#endif // !defined(Maybe_h)
diff --git a/deps/v8_inspector/platform/inspector_protocol/OWNERS b/deps/v8_inspector/platform/inspector_protocol/OWNERS
new file mode 100644
index 0000000000..c34ad775ca
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/OWNERS
@@ -0,0 +1,5 @@
+alph@chromium.org
+caseq@chromium.org
+dgozman@chromium.org
+kozyatinskiy@chromium.org
+pfeldman@chromium.org
diff --git a/deps/v8_inspector/platform/inspector_protocol/Parser.cpp b/deps/v8_inspector/platform/inspector_protocol/Parser.cpp
new file mode 100644
index 0000000000..4425660dca
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/Parser.cpp
@@ -0,0 +1,496 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/inspector_protocol/Parser.h"
+
+#include "platform/inspector_protocol/String16.h"
+#include "platform/inspector_protocol/Values.h"
+#include "wtf/Assertions.h"
+
+namespace blink {
+namespace protocol {
+
+namespace {
+
+const int stackLimit = 1000;
+
+enum Token {
+ ObjectBegin,
+ ObjectEnd,
+ ArrayBegin,
+ ArrayEnd,
+ StringLiteral,
+ Number,
+ BoolTrue,
+ BoolFalse,
+ NullToken,
+ ListSeparator,
+ ObjectPairSeparator,
+ InvalidToken,
+};
+
+const char* const nullString = "null";
+const char* const trueString = "true";
+const char* const falseString = "false";
+
+bool parseConstToken(const UChar* start, const UChar* end, const UChar** tokenEnd, const char* token)
+{
+ while (start < end && *token != '\0' && *start++ == *token++) { }
+ if (*token != '\0')
+ return false;
+ *tokenEnd = start;
+ return true;
+}
+
+bool readInt(const UChar* start, const UChar* end, const UChar** tokenEnd, bool canHaveLeadingZeros)
+{
+ if (start == end)
+ return false;
+ bool haveLeadingZero = '0' == *start;
+ int length = 0;
+ while (start < end && '0' <= *start && *start <= '9') {
+ ++start;
+ ++length;
+ }
+ if (!length)
+ return false;
+ if (!canHaveLeadingZeros && length > 1 && haveLeadingZero)
+ return false;
+ *tokenEnd = start;
+ return true;
+}
+
+bool parseNumberToken(const UChar* start, const UChar* end, const UChar** tokenEnd)
+{
+ // We just grab the number here. We validate the size in DecodeNumber.
+ // According to RFC4627, a valid number is: [minus] int [frac] [exp]
+ if (start == end)
+ return false;
+ UChar c = *start;
+ if ('-' == c)
+ ++start;
+
+ if (!readInt(start, end, &start, false))
+ return false;
+ if (start == end) {
+ *tokenEnd = start;
+ return true;
+ }
+
+ // Optional fraction part
+ c = *start;
+ if ('.' == c) {
+ ++start;
+ if (!readInt(start, end, &start, true))
+ return false;
+ if (start == end) {
+ *tokenEnd = start;
+ return true;
+ }
+ c = *start;
+ }
+
+ // Optional exponent part
+ if ('e' == c || 'E' == c) {
+ ++start;
+ if (start == end)
+ return false;
+ c = *start;
+ if ('-' == c || '+' == c) {
+ ++start;
+ if (start == end)
+ return false;
+ }
+ if (!readInt(start, end, &start, true))
+ return false;
+ }
+
+ *tokenEnd = start;
+ return true;
+}
+
+bool readHexDigits(const UChar* start, const UChar* end, const UChar** tokenEnd, int digits)
+{
+ if (end - start < digits)
+ return false;
+ for (int i = 0; i < digits; ++i) {
+ UChar c = *start++;
+ if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')))
+ return false;
+ }
+ *tokenEnd = start;
+ return true;
+}
+
+bool parseStringToken(const UChar* start, const UChar* end, const UChar** tokenEnd)
+{
+ while (start < end) {
+ UChar c = *start++;
+ if ('\\' == c) {
+ c = *start++;
+ // Make sure the escaped char is valid.
+ switch (c) {
+ case 'x':
+ if (!readHexDigits(start, end, &start, 2))
+ return false;
+ break;
+ case 'u':
+ if (!readHexDigits(start, end, &start, 4))
+ return false;
+ break;
+ case '\\':
+ case '/':
+ case 'b':
+ case 'f':
+ case 'n':
+ case 'r':
+ case 't':
+ case 'v':
+ case '"':
+ break;
+ default:
+ return false;
+ }
+ } else if ('"' == c) {
+ *tokenEnd = start;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool skipComment(const UChar* start, const UChar* end, const UChar** commentEnd)
+{
+ if (start == end)
+ return false;
+
+ if (*start != '/' || start + 1 >= end)
+ return false;
+ ++start;
+
+ if (*start == '/') {
+ // Single line comment, read to newline.
+ for (++start; start < end; ++start) {
+ if (*start == '\n' || *start == '\r') {
+ *commentEnd = start + 1;
+ return true;
+ }
+ }
+ *commentEnd = end;
+ // Comment reaches end-of-input, which is fine.
+ return true;
+ }
+
+ if (*start == '*') {
+ UChar previous = '\0';
+ // Block comment, read until end marker.
+ for (++start; start < end; previous = *start++) {
+ if (previous == '*' && *start == '/') {
+ *commentEnd = start + 1;
+ return true;
+ }
+ }
+ // Block comment must close before end-of-input.
+ return false;
+ }
+
+ return false;
+}
+
+void skipWhitespaceAndComments(const UChar* start, const UChar* end, const UChar** whitespaceEnd)
+{
+ while (start < end) {
+ if (isSpaceOrNewline(*start)) {
+ ++start;
+ } else if (*start == '/') {
+ const UChar* commentEnd;
+ if (!skipComment(start, end, &commentEnd))
+ break;
+ start = commentEnd;
+ } else {
+ break;
+ }
+ }
+ *whitespaceEnd = start;
+}
+
+Token parseToken(const UChar* start, const UChar* end, const UChar** tokenStart, const UChar** tokenEnd)
+{
+ skipWhitespaceAndComments(start, end, tokenStart);
+ start = *tokenStart;
+
+ if (start == end)
+ return InvalidToken;
+
+ switch (*start) {
+ case 'n':
+ if (parseConstToken(start, end, tokenEnd, nullString))
+ return NullToken;
+ break;
+ case 't':
+ if (parseConstToken(start, end, tokenEnd, trueString))
+ return BoolTrue;
+ break;
+ case 'f':
+ if (parseConstToken(start, end, tokenEnd, falseString))
+ return BoolFalse;
+ break;
+ case '[':
+ *tokenEnd = start + 1;
+ return ArrayBegin;
+ case ']':
+ *tokenEnd = start + 1;
+ return ArrayEnd;
+ case ',':
+ *tokenEnd = start + 1;
+ return ListSeparator;
+ case '{':
+ *tokenEnd = start + 1;
+ return ObjectBegin;
+ case '}':
+ *tokenEnd = start + 1;
+ return ObjectEnd;
+ case ':':
+ *tokenEnd = start + 1;
+ return ObjectPairSeparator;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '-':
+ if (parseNumberToken(start, end, tokenEnd))
+ return Number;
+ break;
+ case '"':
+ if (parseStringToken(start + 1, end, tokenEnd))
+ return StringLiteral;
+ break;
+ }
+ return InvalidToken;
+}
+
+inline int hexToInt(UChar c)
+{
+ if ('0' <= c && c <= '9')
+ return c - '0';
+ if ('A' <= c && c <= 'F')
+ return c - 'A' + 10;
+ if ('a' <= c && c <= 'f')
+ return c - 'a' + 10;
+ NOTREACHED();
+ return 0;
+}
+
+bool decodeString(const UChar* start, const UChar* end, String16Builder* output)
+{
+ while (start < end) {
+ UChar c = *start++;
+ if ('\\' != c) {
+ output->append(c);
+ continue;
+ }
+ c = *start++;
+
+ if (c == 'x') {
+ // \x is not supported.
+ return false;
+ }
+
+ 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;
+ case 'v':
+ c = '\v';
+ break;
+ case 'u':
+ c = (hexToInt(*start) << 12) +
+ (hexToInt(*(start + 1)) << 8) +
+ (hexToInt(*(start + 2)) << 4) +
+ hexToInt(*(start + 3));
+ start += 4;
+ break;
+ default:
+ return false;
+ }
+ output->append(c);
+ }
+ return true;
+}
+
+bool decodeString(const UChar* start, const UChar* end, String16* output)
+{
+ if (start == end) {
+ *output = "";
+ return true;
+ }
+ if (start > end)
+ return false;
+ String16Builder buffer;
+ buffer.reserveCapacity(end - start);
+ if (!decodeString(start, end, &buffer))
+ return false;
+ *output = buffer.toString();
+ return true;
+}
+
+std::unique_ptr<Value> buildValue(const UChar* start, const UChar* end, const UChar** valueTokenEnd, int depth)
+{
+ if (depth > stackLimit)
+ return nullptr;
+
+ std::unique_ptr<Value> result;
+ const UChar* tokenStart;
+ const UChar* tokenEnd;
+ Token token = parseToken(start, end, &tokenStart, &tokenEnd);
+ switch (token) {
+ case InvalidToken:
+ return nullptr;
+ case NullToken:
+ result = Value::null();
+ break;
+ case BoolTrue:
+ result = FundamentalValue::create(true);
+ break;
+ case BoolFalse:
+ result = FundamentalValue::create(false);
+ break;
+ case Number: {
+ bool ok;
+ double value = String16::charactersToDouble(tokenStart, tokenEnd - tokenStart, &ok);
+ if (!ok)
+ return nullptr;
+ result = FundamentalValue::create(value);
+ break;
+ }
+ case StringLiteral: {
+ String16 value;
+ bool ok = decodeString(tokenStart + 1, tokenEnd - 1, &value);
+ if (!ok)
+ return nullptr;
+ result = StringValue::create(value);
+ break;
+ }
+ case ArrayBegin: {
+ std::unique_ptr<ListValue> array = ListValue::create();
+ start = tokenEnd;
+ token = parseToken(start, end, &tokenStart, &tokenEnd);
+ while (token != ArrayEnd) {
+ std::unique_ptr<Value> arrayNode = buildValue(start, end, &tokenEnd, depth + 1);
+ if (!arrayNode)
+ return nullptr;
+ array->pushValue(std::move(arrayNode));
+
+ // After a list value, we expect a comma or the end of the list.
+ start = tokenEnd;
+ token = parseToken(start, end, &tokenStart, &tokenEnd);
+ if (token == ListSeparator) {
+ start = tokenEnd;
+ token = parseToken(start, end, &tokenStart, &tokenEnd);
+ if (token == ArrayEnd)
+ return nullptr;
+ } else if (token != ArrayEnd) {
+ // Unexpected value after list value. Bail out.
+ return nullptr;
+ }
+ }
+ if (token != ArrayEnd)
+ return nullptr;
+ result = std::move(array);
+ break;
+ }
+ case ObjectBegin: {
+ std::unique_ptr<DictionaryValue> object = DictionaryValue::create();
+ start = tokenEnd;
+ token = parseToken(start, end, &tokenStart, &tokenEnd);
+ while (token != ObjectEnd) {
+ if (token != StringLiteral)
+ return nullptr;
+ String16 key;
+ if (!decodeString(tokenStart + 1, tokenEnd - 1, &key))
+ return nullptr;
+ start = tokenEnd;
+
+ token = parseToken(start, end, &tokenStart, &tokenEnd);
+ if (token != ObjectPairSeparator)
+ return nullptr;
+ start = tokenEnd;
+
+ std::unique_ptr<Value> value = buildValue(start, end, &tokenEnd, depth + 1);
+ if (!value)
+ return nullptr;
+ object->setValue(key, std::move(value));
+ start = tokenEnd;
+
+ // After a key/value pair, we expect a comma or the end of the
+ // object.
+ token = parseToken(start, end, &tokenStart, &tokenEnd);
+ if (token == ListSeparator) {
+ start = tokenEnd;
+ token = parseToken(start, end, &tokenStart, &tokenEnd);
+ if (token == ObjectEnd)
+ return nullptr;
+ } else if (token != ObjectEnd) {
+ // Unexpected value after last object value. Bail out.
+ return nullptr;
+ }
+ }
+ if (token != ObjectEnd)
+ return nullptr;
+ result = std::move(object);
+ break;
+ }
+
+ default:
+ // We got a token that's not a value.
+ return nullptr;
+ }
+
+ skipWhitespaceAndComments(tokenEnd, end, valueTokenEnd);
+ return result;
+}
+
+std::unique_ptr<Value> parseJSONInternal(const UChar* start, unsigned length)
+{
+ const UChar* end = start + length;
+ const UChar *tokenEnd;
+ std::unique_ptr<Value> value = buildValue(start, end, &tokenEnd, 0);
+ if (!value || tokenEnd != end)
+ return nullptr;
+ return value;
+}
+
+} // anonymous namespace
+
+std::unique_ptr<Value> parseJSON(const String16& json)
+{
+ if (json.isEmpty())
+ return nullptr;
+ return parseJSONInternal(json.characters16(), json.length());
+}
+
+} // namespace protocol
+} // namespace blink
diff --git a/deps/v8_inspector/platform/inspector_protocol/Parser.h b/deps/v8_inspector/platform/inspector_protocol/Parser.h
new file mode 100644
index 0000000000..5f2f44bf64
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/Parser.h
@@ -0,0 +1,22 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef Parser_h
+#define Parser_h
+
+#include "platform/PlatformExport.h"
+#include "platform/inspector_protocol/String16.h"
+#include "wtf/PtrUtil.h"
+
+namespace blink {
+namespace protocol {
+
+class Value;
+
+PLATFORM_EXPORT std::unique_ptr<Value> parseJSON(const String16& json);
+
+} // namespace platform
+} // namespace blink
+
+#endif // !defined(Parser_h)
diff --git a/deps/v8_inspector/platform/inspector_protocol/ParserTest.cpp b/deps/v8_inspector/platform/inspector_protocol/ParserTest.cpp
new file mode 100644
index 0000000000..1dfeb4a4fb
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/ParserTest.cpp
@@ -0,0 +1,504 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/inspector_protocol/Parser.h"
+
+#include "platform/inspector_protocol/String16.h"
+#include "platform/inspector_protocol/Values.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+namespace protocol {
+
+TEST(ParserTest, Reading)
+{
+ protocol::Value* tmpValue;
+ std::unique_ptr<protocol::Value> root;
+ std::unique_ptr<protocol::Value> root2;
+ String16 strVal;
+ int intVal = 0;
+
+ // some whitespace checking
+ root = parseJSON(" null ");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeNull, root->type());
+
+ // Invalid JSON string
+ root = parseJSON("nu");
+ EXPECT_FALSE(root.get());
+
+ // Simple bool
+ root = parseJSON("true ");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeBoolean, root->type());
+
+ // Embedded comment
+ root = parseJSON("40 /*/");
+ EXPECT_FALSE(root.get());
+ root = parseJSON("/* comment */null");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeNull, root->type());
+ root = parseJSON("40 /* comment */");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeNumber, root->type());
+ EXPECT_TRUE(root->asNumber(&intVal));
+ EXPECT_EQ(40, intVal);
+ root = parseJSON("/**/ 40 /* multi-line\n comment */ // more comment");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeNumber, root->type());
+ EXPECT_TRUE(root->asNumber(&intVal));
+ EXPECT_EQ(40, intVal);
+ root = parseJSON("true // comment");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeBoolean, root->type());
+ root = parseJSON("/* comment */\"sample string\"");
+ ASSERT_TRUE(root.get());
+ EXPECT_TRUE(root->asString(&strVal));
+ EXPECT_EQ("sample string", strVal);
+ root = parseJSON("[1, /* comment, 2 ] */ \n 3]");
+ ASSERT_TRUE(root.get());
+ protocol::ListValue* list = ListValue::cast(root.get());
+ ASSERT_TRUE(list);
+ EXPECT_EQ(2u, list->size());
+ tmpValue = list->at(0);
+ ASSERT_TRUE(tmpValue);
+ EXPECT_TRUE(tmpValue->asNumber(&intVal));
+ EXPECT_EQ(1, intVal);
+ tmpValue = list->at(1);
+ ASSERT_TRUE(tmpValue);
+ EXPECT_TRUE(tmpValue->asNumber(&intVal));
+ EXPECT_EQ(3, intVal);
+ root = parseJSON("[1, /*a*/2, 3]");
+ ASSERT_TRUE(root.get());
+ list = ListValue::cast(root.get());
+ ASSERT_TRUE(list);
+ EXPECT_EQ(3u, list->size());
+ root = parseJSON("/* comment **/42");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeNumber, root->type());
+ EXPECT_TRUE(root->asNumber(&intVal));
+ EXPECT_EQ(42, intVal);
+ root = parseJSON(
+ "/* comment **/\n"
+ "// */ 43\n"
+ "44");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeNumber, root->type());
+ EXPECT_TRUE(root->asNumber(&intVal));
+ EXPECT_EQ(44, intVal);
+
+ // Test number formats
+ root = parseJSON("43");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeNumber, root->type());
+ EXPECT_TRUE(root->asNumber(&intVal));
+ EXPECT_EQ(43, intVal);
+
+ // According to RFC4627, oct, hex, and leading zeros are invalid JSON.
+ root = parseJSON("043");
+ EXPECT_FALSE(root.get());
+ root = parseJSON("0x43");
+ EXPECT_FALSE(root.get());
+ root = parseJSON("00");
+ EXPECT_FALSE(root.get());
+
+ // Test 0 (which needs to be special cased because of the leading zero
+ // clause).
+ root = parseJSON("0");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeNumber, root->type());
+ intVal = 1;
+ EXPECT_TRUE(root->asNumber(&intVal));
+ EXPECT_EQ(0, intVal);
+
+ // Numbers that overflow ints should succeed, being internally promoted to
+ // storage as doubles
+ root = parseJSON("2147483648");
+ ASSERT_TRUE(root.get());
+ double doubleVal;
+ EXPECT_EQ(Value::TypeNumber, root->type());
+ doubleVal = 0.0;
+ EXPECT_TRUE(root->asNumber(&doubleVal));
+ EXPECT_DOUBLE_EQ(2147483648.0, doubleVal);
+ root = parseJSON("-2147483649");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeNumber, root->type());
+ doubleVal = 0.0;
+ EXPECT_TRUE(root->asNumber(&doubleVal));
+ EXPECT_DOUBLE_EQ(-2147483649.0, doubleVal);
+
+ // Parse a double
+ root = parseJSON("43.1");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeNumber, root->type());
+ doubleVal = 0.0;
+ EXPECT_TRUE(root->asNumber(&doubleVal));
+ EXPECT_DOUBLE_EQ(43.1, doubleVal);
+
+ root = parseJSON("4.3e-1");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeNumber, root->type());
+ doubleVal = 0.0;
+ EXPECT_TRUE(root->asNumber(&doubleVal));
+ EXPECT_DOUBLE_EQ(.43, doubleVal);
+
+ root = parseJSON("2.1e0");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeNumber, root->type());
+ doubleVal = 0.0;
+ EXPECT_TRUE(root->asNumber(&doubleVal));
+ EXPECT_DOUBLE_EQ(2.1, doubleVal);
+
+ root = parseJSON("2.1e+0001");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeNumber, root->type());
+ doubleVal = 0.0;
+ EXPECT_TRUE(root->asNumber(&doubleVal));
+ EXPECT_DOUBLE_EQ(21.0, doubleVal);
+
+ root = parseJSON("0.01");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeNumber, root->type());
+ doubleVal = 0.0;
+ EXPECT_TRUE(root->asNumber(&doubleVal));
+ EXPECT_DOUBLE_EQ(0.01, doubleVal);
+
+ root = parseJSON("1.00");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeNumber, root->type());
+ doubleVal = 0.0;
+ EXPECT_TRUE(root->asNumber(&doubleVal));
+ EXPECT_DOUBLE_EQ(1.0, doubleVal);
+
+ // Fractional parts must have a digit before and after the decimal point.
+ root = parseJSON("1.");
+ EXPECT_FALSE(root.get());
+ root = parseJSON(".1");
+ EXPECT_FALSE(root.get());
+ root = parseJSON("1.e10");
+ EXPECT_FALSE(root.get());
+
+ // Exponent must have a digit following the 'e'.
+ root = parseJSON("1e");
+ EXPECT_FALSE(root.get());
+ root = parseJSON("1E");
+ EXPECT_FALSE(root.get());
+ root = parseJSON("1e1.");
+ EXPECT_FALSE(root.get());
+ root = parseJSON("1e1.0");
+ EXPECT_FALSE(root.get());
+
+ // INF/-INF/NaN are not valid
+ root = parseJSON("NaN");
+ EXPECT_FALSE(root.get());
+ root = parseJSON("nan");
+ EXPECT_FALSE(root.get());
+ root = parseJSON("inf");
+ EXPECT_FALSE(root.get());
+
+ // Invalid number formats
+ root = parseJSON("4.3.1");
+ EXPECT_FALSE(root.get());
+ root = parseJSON("4e3.1");
+ EXPECT_FALSE(root.get());
+
+ // Test string parser
+ root = parseJSON("\"hello world\"");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeString, root->type());
+ EXPECT_TRUE(root->asString(&strVal));
+ EXPECT_EQ("hello world", strVal);
+
+ // Empty string
+ root = parseJSON("\"\"");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeString, root->type());
+ EXPECT_TRUE(root->asString(&strVal));
+ EXPECT_EQ("", strVal);
+
+ // Test basic string escapes
+ root = parseJSON("\" \\\"\\\\\\/\\b\\f\\n\\r\\t\\v\"");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeString, root->type());
+ EXPECT_TRUE(root->asString(&strVal));
+ EXPECT_EQ(" \"\\/\b\f\n\r\t\v", strVal);
+
+ // Test hex and unicode escapes including the null character.
+ root = parseJSON("\"\\x41\\x00\\u1234\"");
+ EXPECT_FALSE(root.get());
+
+ // Test invalid strings
+ root = parseJSON("\"no closing quote");
+ EXPECT_FALSE(root.get());
+ root = parseJSON("\"\\z invalid escape char\"");
+ EXPECT_FALSE(root.get());
+ root = parseJSON("\"not enough escape chars\\u123\"");
+ EXPECT_FALSE(root.get());
+ root = parseJSON("\"extra backslash at end of input\\\"");
+ EXPECT_FALSE(root.get());
+
+ // Basic array
+ root = parseJSON("[true, false, null]");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeArray, root->type());
+ list = ListValue::cast(root.get());
+ ASSERT_TRUE(list);
+ EXPECT_EQ(3U, list->size());
+
+ // Empty array
+ root = parseJSON("[]");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeArray, root->type());
+ list = ListValue::cast(root.get());
+ ASSERT_TRUE(list);
+ EXPECT_EQ(0U, list->size());
+
+ // Nested arrays
+ root = parseJSON("[[true], [], [false, [], [null]], null]");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeArray, root->type());
+ list = ListValue::cast(root.get());
+ ASSERT_TRUE(list);
+ EXPECT_EQ(4U, list->size());
+
+ // Invalid, missing close brace.
+ root = parseJSON("[[true], [], [false, [], [null]], null");
+ EXPECT_FALSE(root.get());
+
+ // Invalid, too many commas
+ root = parseJSON("[true,, null]");
+ EXPECT_FALSE(root.get());
+
+ // Invalid, no commas
+ root = parseJSON("[true null]");
+ EXPECT_FALSE(root.get());
+
+ // Invalid, trailing comma
+ root = parseJSON("[true,]");
+ EXPECT_FALSE(root.get());
+
+ root = parseJSON("[true]");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeArray, root->type());
+ list = ListValue::cast(root.get());
+ ASSERT_TRUE(list);
+ EXPECT_EQ(1U, list->size());
+ tmpValue = list->at(0);
+ ASSERT_TRUE(tmpValue);
+ EXPECT_EQ(Value::TypeBoolean, tmpValue->type());
+ bool boolValue = false;
+ EXPECT_TRUE(tmpValue->asBoolean(&boolValue));
+ EXPECT_TRUE(boolValue);
+
+ // Don't allow empty elements.
+ root = parseJSON("[,]");
+ EXPECT_FALSE(root.get());
+ root = parseJSON("[true,,]");
+ EXPECT_FALSE(root.get());
+ root = parseJSON("[,true,]");
+ EXPECT_FALSE(root.get());
+ root = parseJSON("[true,,false]");
+ EXPECT_FALSE(root.get());
+
+ // Test objects
+ root = parseJSON("{}");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeObject, root->type());
+
+ root = parseJSON("{\"number\":9.87654321, \"null\":null , \"S\" : \"str\" }");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeObject, root->type());
+ protocol::DictionaryValue* objectVal = DictionaryValue::cast(root.get());
+ ASSERT_TRUE(objectVal);
+ doubleVal = 0.0;
+ EXPECT_TRUE(objectVal->getNumber("number", &doubleVal));
+ EXPECT_DOUBLE_EQ(9.87654321, doubleVal);
+ protocol::Value* nullVal = objectVal->get("null");
+ ASSERT_TRUE(nullVal);
+ EXPECT_EQ(Value::TypeNull, nullVal->type());
+ EXPECT_TRUE(objectVal->getString("S", &strVal));
+ EXPECT_EQ("str", strVal);
+
+ // Test newline equivalence.
+ root2 = parseJSON(
+ "{\n"
+ " \"number\":9.87654321,\n"
+ " \"null\":null,\n"
+ " \"S\":\"str\"\n"
+ "}\n");
+ ASSERT_TRUE(root2.get());
+ EXPECT_EQ(root->toJSONString(), root2->toJSONString());
+
+ root2 = parseJSON(
+ "{\r\n"
+ " \"number\":9.87654321,\r\n"
+ " \"null\":null,\r\n"
+ " \"S\":\"str\"\r\n"
+ "}\r\n");
+ ASSERT_TRUE(root2.get());
+ EXPECT_EQ(root->toJSONString(), root2->toJSONString());
+
+ // Test nesting
+ root = parseJSON("{\"inner\":{\"array\":[true]},\"false\":false,\"d\":{}}");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeObject, root->type());
+ objectVal = DictionaryValue::cast(root.get());
+ ASSERT_TRUE(objectVal);
+ protocol::DictionaryValue* innerObject = objectVal->getObject("inner");
+ ASSERT_TRUE(innerObject);
+ protocol::ListValue* innerArray = innerObject->getArray("array");
+ ASSERT_TRUE(innerArray);
+ EXPECT_EQ(1U, innerArray->size());
+ boolValue = true;
+ EXPECT_TRUE(objectVal->getBoolean("false", &boolValue));
+ EXPECT_FALSE(boolValue);
+ innerObject = objectVal->getObject("d");
+ EXPECT_TRUE(innerObject);
+
+ // Test keys with periods
+ root = parseJSON("{\"a.b\":3,\"c\":2,\"d.e.f\":{\"g.h.i.j\":1}}");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeObject, root->type());
+ objectVal = DictionaryValue::cast(root.get());
+ ASSERT_TRUE(objectVal);
+ int integerValue = 0;
+ EXPECT_TRUE(objectVal->getNumber("a.b", &integerValue));
+ EXPECT_EQ(3, integerValue);
+ EXPECT_TRUE(objectVal->getNumber("c", &integerValue));
+ EXPECT_EQ(2, integerValue);
+ innerObject = objectVal->getObject("d.e.f");
+ ASSERT_TRUE(innerObject);
+ EXPECT_EQ(1U, innerObject->size());
+ EXPECT_TRUE(innerObject->getNumber("g.h.i.j", &integerValue));
+ EXPECT_EQ(1, integerValue);
+
+ root = parseJSON("{\"a\":{\"b\":2},\"a.b\":1}");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeObject, root->type());
+ objectVal = DictionaryValue::cast(root.get());
+ ASSERT_TRUE(objectVal);
+ innerObject = objectVal->getObject("a");
+ ASSERT_TRUE(innerObject);
+ EXPECT_TRUE(innerObject->getNumber("b", &integerValue));
+ EXPECT_EQ(2, integerValue);
+ EXPECT_TRUE(objectVal->getNumber("a.b", &integerValue));
+ EXPECT_EQ(1, integerValue);
+
+ // Invalid, no closing brace
+ root = parseJSON("{\"a\": true");
+ EXPECT_FALSE(root.get());
+
+ // Invalid, keys must be quoted
+ root = parseJSON("{foo:true}");
+ EXPECT_FALSE(root.get());
+
+ // Invalid, trailing comma
+ root = parseJSON("{\"a\":true,}");
+ EXPECT_FALSE(root.get());
+
+ // Invalid, too many commas
+ root = parseJSON("{\"a\":true,,\"b\":false}");
+ EXPECT_FALSE(root.get());
+
+ // Invalid, no separator
+ root = parseJSON("{\"a\" \"b\"}");
+ EXPECT_FALSE(root.get());
+
+ // Invalid, lone comma.
+ root = parseJSON("{,}");
+ EXPECT_FALSE(root.get());
+ root = parseJSON("{\"a\":true,,}");
+ EXPECT_FALSE(root.get());
+ root = parseJSON("{,\"a\":true}");
+ EXPECT_FALSE(root.get());
+ root = parseJSON("{\"a\":true,,\"b\":false}");
+ EXPECT_FALSE(root.get());
+
+ // Test stack overflow
+ String16Builder evil;
+ evil.reserveCapacity(2000000);
+ for (int i = 0; i < 1000000; ++i)
+ evil.append('[');
+ for (int i = 0; i < 1000000; ++i)
+ evil.append(']');
+ root = parseJSON(evil.toString());
+ EXPECT_FALSE(root.get());
+
+ // A few thousand adjacent lists is fine.
+ String16Builder notEvil;
+ notEvil.reserveCapacity(15010);
+ notEvil.append('[');
+ for (int i = 0; i < 5000; ++i)
+ notEvil.append("[],");
+ notEvil.append("[]]");
+ root = parseJSON(notEvil.toString());
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeArray, root->type());
+ list = ListValue::cast(root.get());
+ ASSERT_TRUE(list);
+ EXPECT_EQ(5001U, list->size());
+
+ // Test utf8 encoded input
+ root = parseJSON("\"\\xe7\\xbd\\x91\\xe9\\xa1\\xb5\"");
+ ASSERT_FALSE(root.get());
+
+ // Test utf16 encoded strings.
+ root = parseJSON("\"\\u20ac3,14\"");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeString, root->type());
+ EXPECT_TRUE(root->asString(&strVal));
+ UChar tmp2[] = {0x20ac, 0x33, 0x2c, 0x31, 0x34};
+ EXPECT_EQ(String16(tmp2, 5), strVal);
+
+ root = parseJSON("\"\\ud83d\\udca9\\ud83d\\udc6c\"");
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(Value::TypeString, root->type());
+ EXPECT_TRUE(root->asString(&strVal));
+ UChar tmp3[] = {0xd83d, 0xdca9, 0xd83d, 0xdc6c};
+ EXPECT_EQ(String16(tmp3, 4), strVal);
+
+ // Test literal root objects.
+ root = parseJSON("null");
+ EXPECT_EQ(Value::TypeNull, root->type());
+
+ root = parseJSON("true");
+ ASSERT_TRUE(root.get());
+ EXPECT_TRUE(root->asBoolean(&boolValue));
+ EXPECT_TRUE(boolValue);
+
+ root = parseJSON("10");
+ ASSERT_TRUE(root.get());
+ EXPECT_TRUE(root->asNumber(&integerValue));
+ EXPECT_EQ(10, integerValue);
+
+ root = parseJSON("\"root\"");
+ ASSERT_TRUE(root.get());
+ EXPECT_TRUE(root->asString(&strVal));
+ EXPECT_EQ("root", strVal);
+}
+
+TEST(ParserTest, InvalidSanity)
+{
+ const char* const invalidJson[] = {
+ "/* test *",
+ "{\"foo\"",
+ "{\"foo\":",
+ " [",
+ "\"\\u123g\"",
+ "{\n\"eh:\n}",
+ "////",
+ "*/**/",
+ "/**/",
+ "/*/",
+ "//**/"
+ };
+
+ for (size_t i = 0; i < 11; ++i) {
+ std::unique_ptr<protocol::Value> result = parseJSON(invalidJson[i]);
+ EXPECT_FALSE(result.get());
+ }
+}
+
+} // namespace protocol
+} // namespace blink
diff --git a/deps/v8_inspector/platform/inspector_protocol/String16.h b/deps/v8_inspector/platform/inspector_protocol/String16.h
new file mode 100644
index 0000000000..6a1b4a09de
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/String16.h
@@ -0,0 +1,14 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef String16_h
+#define String16_h
+
+#if V8_INSPECTOR_USE_STL
+#include "platform/inspector_protocol/String16STL.h"
+#else
+#include "platform/inspector_protocol/String16WTF.h"
+#endif // V8_INSPECTOR_USE_STL
+
+#endif // !defined(String16_h)
diff --git a/deps/v8_inspector/platform/inspector_protocol/String16STL.cpp b/deps/v8_inspector/platform/inspector_protocol/String16STL.cpp
new file mode 100644
index 0000000000..9f6afbf075
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/String16STL.cpp
@@ -0,0 +1,602 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/inspector_protocol/String16STL.h"
+
+#include <algorithm>
+#include <cctype>
+#include <cstdio>
+#include <functional>
+#include <locale>
+
+#define DCHECK(k)
+
+namespace blink {
+namespace protocol {
+
+const UChar replacementCharacter = 0xFFFD;
+
+template<typename CharType> inline bool isASCII(CharType c)
+{
+ return !(c & ~0x7F);
+}
+
+template<typename CharType> inline bool isASCIIAlpha(CharType c)
+{
+ return (c | 0x20) >= 'a' && (c | 0x20) <= 'z';
+}
+
+template<typename CharType> inline bool isASCIIDigit(CharType c)
+{
+ return c >= '0' && c <= '9';
+}
+
+template<typename CharType> inline bool isASCIIAlphanumeric(CharType c)
+{
+ return isASCIIDigit(c) || isASCIIAlpha(c);
+}
+
+template<typename CharType> inline bool isASCIIHexDigit(CharType c)
+{
+ return isASCIIDigit(c) || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f');
+}
+
+template<typename CharType> inline bool isASCIIOctalDigit(CharType c)
+{
+ return (c >= '0') & (c <= '7');
+}
+
+template<typename CharType> inline bool isASCIIPrintable(CharType c)
+{
+ return c >= ' ' && c <= '~';
+}
+
+/*
+ Statistics from a run of Apple's page load test for callers of isASCIISpace:
+
+ character count
+ --------- -----
+ non-spaces 689383
+ 20 space 294720
+ 0A \n 89059
+ 09 \t 28320
+ 0D \r 0
+ 0C \f 0
+ 0B \v 0
+ */
+template<typename CharType> inline bool isASCIISpace(CharType c)
+{
+ return c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9));
+}
+
+extern const LChar ASCIICaseFoldTable[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+template<typename CharType> inline int toASCIIHexValue(CharType c)
+{
+ DCHECK(isASCIIHexDigit(c));
+ return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF;
+}
+
+template<typename CharType> inline int toASCIIHexValue(CharType upperValue, CharType lowerValue)
+{
+ DCHECK(isASCIIHexDigit(upperValue) && isASCIIHexDigit(lowerValue));
+ return ((toASCIIHexValue(upperValue) << 4) & 0xF0) | toASCIIHexValue(lowerValue);
+}
+
+inline char lowerNibbleToASCIIHexDigit(char c)
+{
+ char nibble = c & 0xF;
+ return nibble < 10 ? '0' + nibble : 'A' + nibble - 10;
+}
+
+inline char upperNibbleToASCIIHexDigit(char c)
+{
+ char nibble = (c >> 4) & 0xF;
+ return nibble < 10 ? '0' + nibble : 'A' + nibble - 10;
+}
+
+template<typename CharType> inline bool isASCIIAlphaCaselessEqual(CharType cssCharacter, char character)
+{
+ // This function compares a (preferrably) constant ASCII
+ // lowercase letter to any input character.
+ DCHECK(character >= 'a' && character <= 'z');
+ return LIKELY(toASCIILowerUnchecked(cssCharacter) == character);
+}
+
+inline int inlineUTF8SequenceLengthNonASCII(char b0)
+{
+ if ((b0 & 0xC0) != 0xC0)
+ return 0;
+ if ((b0 & 0xE0) == 0xC0)
+ return 2;
+ if ((b0 & 0xF0) == 0xE0)
+ return 3;
+ if ((b0 & 0xF8) == 0xF0)
+ return 4;
+ return 0;
+}
+
+inline int inlineUTF8SequenceLength(char b0)
+{
+ return isASCII(b0) ? 1 : inlineUTF8SequenceLengthNonASCII(b0);
+}
+
+// Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
+// into the first byte, depending on how many bytes follow. There are
+// as many entries in this table as there are UTF-8 sequence types.
+// (I.e., one byte sequence, two byte... etc.). Remember that sequences
+// for *legal* UTF-8 will be 4 or fewer bytes total.
+static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+typedef enum {
+ conversionOK, // conversion successful
+ sourceExhausted, // partial character in source, but hit end
+ targetExhausted, // insuff. room in target for conversion
+ sourceIllegal // source sequence is illegal/malformed
+} ConversionResult;
+
+ConversionResult convertLatin1ToUTF8(
+ const LChar** sourceStart, const LChar* sourceEnd,
+ char** targetStart, char* targetEnd)
+{
+ ConversionResult result = conversionOK;
+ const LChar* source = *sourceStart;
+ char* target = *targetStart;
+ while (source < sourceEnd) {
+ UChar32 ch;
+ unsigned short bytesToWrite = 0;
+ const UChar32 byteMask = 0xBF;
+ const UChar32 byteMark = 0x80;
+ const LChar* oldSource = source; // In case we have to back up because of target overflow.
+ ch = static_cast<unsigned short>(*source++);
+
+ // Figure out how many bytes the result will require
+ if (ch < (UChar32)0x80)
+ bytesToWrite = 1;
+ else
+ bytesToWrite = 2;
+
+ target += bytesToWrite;
+ if (target > targetEnd) {
+ source = oldSource; // Back up source pointer!
+ target -= bytesToWrite;
+ result = targetExhausted;
+ break;
+ }
+ switch (bytesToWrite) { // note: everything falls through.
+ case 2:
+ *--target = (char)((ch | byteMark) & byteMask);
+ ch >>= 6;
+ case 1:
+ *--target = (char)(ch | firstByteMark[bytesToWrite]);
+ }
+ target += bytesToWrite;
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+ConversionResult convertUTF16ToUTF8(
+ const UChar** sourceStart, const UChar* sourceEnd,
+ char** targetStart, char* targetEnd, bool strict)
+{
+ ConversionResult result = conversionOK;
+ const UChar* source = *sourceStart;
+ char* target = *targetStart;
+ while (source < sourceEnd) {
+ UChar32 ch;
+ unsigned short bytesToWrite = 0;
+ const UChar32 byteMask = 0xBF;
+ const UChar32 byteMark = 0x80;
+ const UChar* oldSource = source; // In case we have to back up because of target overflow.
+ ch = static_cast<unsigned short>(*source++);
+ // If we have a surrogate pair, convert to UChar32 first.
+ if (ch >= 0xD800 && ch <= 0xDBFF) {
+ // If the 16 bits following the high surrogate are in the source buffer...
+ if (source < sourceEnd) {
+ UChar32 ch2 = static_cast<unsigned short>(*source);
+ // If it's a low surrogate, convert to UChar32.
+ if (ch2 >= 0xDC00 && ch2 <= 0xDFFF) {
+ ch = ((ch - 0xD800) << 10) + (ch2 - 0xDC00) + 0x0010000;
+ ++source;
+ } else if (strict) { // it's an unpaired high surrogate
+ --source; // return to the illegal value itself
+ result = sourceIllegal;
+ break;
+ }
+ } else { // We don't have the 16 bits following the high surrogate.
+ --source; // return to the high surrogate
+ result = sourceExhausted;
+ break;
+ }
+ } else if (strict) {
+ // UTF-16 surrogate values are illegal in UTF-32
+ if (ch >= 0xDC00 && ch <= 0xDFFF) {
+ --source; // return to the illegal value itself
+ result = sourceIllegal;
+ break;
+ }
+ }
+ // Figure out how many bytes the result will require
+ if (ch < (UChar32)0x80) {
+ bytesToWrite = 1;
+ } else if (ch < (UChar32)0x800) {
+ bytesToWrite = 2;
+ } else if (ch < (UChar32)0x10000) {
+ bytesToWrite = 3;
+ } else if (ch < (UChar32)0x110000) {
+ bytesToWrite = 4;
+ } else {
+ bytesToWrite = 3;
+ ch = replacementCharacter;
+ }
+
+ target += bytesToWrite;
+ if (target > targetEnd) {
+ source = oldSource; // Back up source pointer!
+ target -= bytesToWrite;
+ result = targetExhausted;
+ break;
+ }
+ switch (bytesToWrite) { // note: everything falls through.
+ case 4:
+ *--target = (char)((ch | byteMark) & byteMask);
+ ch >>= 6;
+ case 3:
+ *--target = (char)((ch | byteMark) & byteMask);
+ ch >>= 6;
+ case 2:
+ *--target = (char)((ch | byteMark) & byteMask);
+ ch >>= 6;
+ case 1:
+ *--target = (char)(ch | firstByteMark[bytesToWrite]);
+ }
+ target += bytesToWrite;
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/**
+ * Is this code point a BMP code point (U+0000..U+ffff)?
+ * @param c 32-bit code point
+ * @return TRUE or FALSE
+ * @stable ICU 2.8
+ */
+#define U_IS_BMP(c) ((uint32_t)(c)<=0xffff)
+
+/**
+ * Is this code point a supplementary code point (U+10000..U+10ffff)?
+ * @param c 32-bit code point
+ * @return TRUE or FALSE
+ * @stable ICU 2.8
+ */
+#define U_IS_SUPPLEMENTARY(c) ((uint32_t)((c)-0x10000)<=0xfffff)
+
+/**
+ * Is this code point a surrogate (U+d800..U+dfff)?
+ * @param c 32-bit code point
+ * @return TRUE or FALSE
+ * @stable ICU 2.4
+ */
+#define U_IS_SURROGATE(c) (((c)&0xfffff800)==0xd800)
+
+/**
+ * Get the lead surrogate (0xd800..0xdbff) for a
+ * supplementary code point (0x10000..0x10ffff).
+ * @param supplementary 32-bit code point (U+10000..U+10ffff)
+ * @return lead surrogate (U+d800..U+dbff) for supplementary
+ * @stable ICU 2.4
+ */
+#define U16_LEAD(supplementary) (UChar)(((supplementary)>>10)+0xd7c0)
+
+/**
+ * Get the trail surrogate (0xdc00..0xdfff) for a
+ * supplementary code point (0x10000..0x10ffff).
+ * @param supplementary 32-bit code point (U+10000..U+10ffff)
+ * @return trail surrogate (U+dc00..U+dfff) for supplementary
+ * @stable ICU 2.4
+ */
+#define U16_TRAIL(supplementary) (UChar)(((supplementary)&0x3ff)|0xdc00)
+
+// This must be called with the length pre-determined by the first byte.
+// If presented with a length > 4, this returns false. The Unicode
+// definition of UTF-8 goes up to 4-byte sequences.
+static bool isLegalUTF8(const unsigned char* source, int length)
+{
+ unsigned char a;
+ const unsigned char* srcptr = source + length;
+ switch (length) {
+ default:
+ return false;
+ // Everything else falls through when "true"...
+ case 4:
+ if ((a = (*--srcptr)) < 0x80 || a > 0xBF)
+ return false;
+ case 3:
+ if ((a = (*--srcptr)) < 0x80 || a > 0xBF)
+ return false;
+ case 2:
+ if ((a = (*--srcptr)) > 0xBF)
+ return false;
+
+ // no fall-through in this inner switch
+ switch (*source) {
+ case 0xE0:
+ if (a < 0xA0)
+ return false;
+ break;
+ case 0xED:
+ if (a > 0x9F)
+ return false;
+ break;
+ case 0xF0:
+ if (a < 0x90)
+ return false;
+ break;
+ case 0xF4:
+ if (a > 0x8F)
+ return false;
+ break;
+ default:
+ if (a < 0x80)
+ return false;
+ }
+
+ case 1:
+ if (*source >= 0x80 && *source < 0xC2)
+ return false;
+ }
+ if (*source > 0xF4)
+ return false;
+ return true;
+}
+
+// Magic values subtracted from a buffer value during UTF8 conversion.
+// This table contains as many values as there might be trailing bytes
+// in a UTF-8 sequence.
+static const UChar32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 0x03C82080UL, static_cast<UChar32>(0xFA082080UL), static_cast<UChar32>(0x82082080UL) };
+
+static inline UChar32 readUTF8Sequence(const char*& sequence, unsigned length)
+{
+ UChar32 character = 0;
+
+ // The cases all fall through.
+ switch (length) {
+ case 6:
+ character += static_cast<unsigned char>(*sequence++);
+ character <<= 6;
+ case 5:
+ character += static_cast<unsigned char>(*sequence++);
+ character <<= 6;
+ case 4:
+ character += static_cast<unsigned char>(*sequence++);
+ character <<= 6;
+ case 3:
+ character += static_cast<unsigned char>(*sequence++);
+ character <<= 6;
+ case 2:
+ character += static_cast<unsigned char>(*sequence++);
+ character <<= 6;
+ case 1:
+ character += static_cast<unsigned char>(*sequence++);
+ }
+
+ return character - offsetsFromUTF8[length - 1];
+}
+
+ConversionResult convertUTF8ToUTF16(
+ const char** sourceStart, const char* sourceEnd,
+ UChar** targetStart, UChar* targetEnd, bool* sourceAllASCII, bool strict)
+{
+ ConversionResult result = conversionOK;
+ const char* source = *sourceStart;
+ UChar* target = *targetStart;
+ UChar orAllData = 0;
+ while (source < sourceEnd) {
+ int utf8SequenceLength = inlineUTF8SequenceLength(*source);
+ if (sourceEnd - source < utf8SequenceLength) {
+ result = sourceExhausted;
+ break;
+ }
+ // Do this check whether lenient or strict
+ if (!isLegalUTF8(reinterpret_cast<const unsigned char*>(source), utf8SequenceLength)) {
+ result = sourceIllegal;
+ break;
+ }
+
+ UChar32 character = readUTF8Sequence(source, utf8SequenceLength);
+
+ if (target >= targetEnd) {
+ source -= utf8SequenceLength; // Back up source pointer!
+ result = targetExhausted;
+ break;
+ }
+
+ if (U_IS_BMP(character)) {
+ // UTF-16 surrogate values are illegal in UTF-32
+ if (U_IS_SURROGATE(character)) {
+ if (strict) {
+ source -= utf8SequenceLength; // return to the illegal value itself
+ result = sourceIllegal;
+ break;
+ }
+ *target++ = replacementCharacter;
+ orAllData |= replacementCharacter;
+ } else {
+ *target++ = static_cast<UChar>(character); // normal case
+ orAllData |= character;
+ }
+ } else if (U_IS_SUPPLEMENTARY(character)) {
+ // target is a character in range 0xFFFF - 0x10FFFF
+ if (target + 1 >= targetEnd) {
+ source -= utf8SequenceLength; // Back up source pointer!
+ result = targetExhausted;
+ break;
+ }
+ *target++ = U16_LEAD(character);
+ *target++ = U16_TRAIL(character);
+ orAllData = 0xffff;
+ } else {
+ if (strict) {
+ source -= utf8SequenceLength; // return to the start
+ result = sourceIllegal;
+ break; // Bail out; shouldn't continue
+ } else {
+ *target++ = replacementCharacter;
+ orAllData |= replacementCharacter;
+ }
+ }
+ }
+ *sourceStart = source;
+ *targetStart = target;
+
+ if (sourceAllASCII)
+ *sourceAllASCII = !(orAllData & ~0x7f);
+
+ return result;
+}
+
+// Helper to write a three-byte UTF-8 code point to the buffer, caller must check room is available.
+static inline void putUTF8Triple(char*& buffer, UChar ch)
+{
+ DCHECK(ch >= 0x0800);
+ *buffer++ = static_cast<char>(((ch >> 12) & 0x0F) | 0xE0);
+ *buffer++ = static_cast<char>(((ch >> 6) & 0x3F) | 0x80);
+ *buffer++ = static_cast<char>((ch & 0x3F) | 0x80);
+}
+
+String16 String16::fromUTF8(const char* stringStart, size_t length)
+{
+ if (!stringStart || !length)
+ return String16();
+
+ std::vector<UChar> buffer(length);
+ UChar* bufferStart = buffer.data();
+
+ UChar* bufferCurrent = bufferStart;
+ const char* stringCurrent = stringStart;
+ if (convertUTF8ToUTF16(&stringCurrent, stringStart + length, &bufferCurrent, bufferCurrent + buffer.size(), 0, true) != conversionOK)
+ return String16();
+
+ unsigned utf16Length = bufferCurrent - bufferStart;
+ return String16(bufferStart, utf16Length);
+}
+
+// trim from start
+static inline wstring &ltrim(wstring &s)
+{
+ s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
+ return s;
+}
+
+// trim from end
+static inline wstring &rtrim(wstring &s)
+{
+ s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
+ return s;
+}
+
+// trim from both ends
+static inline wstring &trim(wstring &s)
+{
+ return ltrim(rtrim(s));
+}
+
+// static
+std::string String16::intToString(int i)
+{
+ char buffer[50];
+ std::sprintf(buffer, "%d", i);
+ return std::string(buffer);
+}
+
+// static
+std::string String16::doubleToString(double d)
+{
+ char buffer[100];
+ std::sprintf(buffer, "%f", d);
+ return std::string(buffer);
+}
+
+std::string String16::utf8() const
+{
+ unsigned length = this->length();
+
+ if (!length)
+ return std::string("");
+
+ // Allocate a buffer big enough to hold all the characters
+ // (an individual UTF-16 UChar can only expand to 3 UTF-8 bytes).
+ // Optimization ideas, if we find this function is hot:
+ // * We could speculatively create a CStringBuffer to contain 'length'
+ // characters, and resize if necessary (i.e. if the buffer contains
+ // non-ascii characters). (Alternatively, scan the buffer first for
+ // ascii characters, so we know this will be sufficient).
+ // * We could allocate a CStringBuffer with an appropriate size to
+ // have a good chance of being able to write the string into the
+ // buffer without reallocing (say, 1.5 x length).
+ if (length > std::numeric_limits<unsigned>::max() / 3)
+ return std::string();
+ std::vector<char> bufferVector(length * 3);
+ char* buffer = bufferVector.data();
+ const UChar* characters = m_impl.data();
+
+ bool strict = false;
+ ConversionResult result = convertUTF16ToUTF8(&characters, characters + length, &buffer, buffer + bufferVector.size(), strict);
+ DCHECK(result != targetExhausted); // (length * 3) should be sufficient for any conversion
+
+ // Only produced from strict conversion.
+ if (result == sourceIllegal) {
+ DCHECK(strict);
+ return std::string();
+ }
+
+ // Check for an unconverted high surrogate.
+ if (result == sourceExhausted) {
+ if (strict)
+ return std::string();
+ // This should be one unpaired high surrogate. Treat it the same
+ // was as an unpaired high surrogate would have been handled in
+ // the middle of a string with non-strict conversion - which is
+ // to say, simply encode it to UTF-8.
+ DCHECK((characters + 1) == (m_impl.data() + length));
+ DCHECK((*characters >= 0xD800) && (*characters <= 0xDBFF));
+ // There should be room left, since one UChar hasn't been
+ // converted.
+ DCHECK((buffer + 3) <= (buffer + bufferVector.size()));
+ putUTF8Triple(buffer, *characters);
+ }
+
+ return std::string(bufferVector.data(), buffer - bufferVector.data());
+}
+
+String16 String16::stripWhiteSpace() const
+{
+ wstring result(m_impl);
+ trim(result);
+ return result;
+}
+
+} // namespace protocol
+} // namespace blink
diff --git a/deps/v8_inspector/platform/inspector_protocol/String16STL.h b/deps/v8_inspector/platform/inspector_protocol/String16STL.h
new file mode 100644
index 0000000000..2ac0e2ea7f
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/String16STL.h
@@ -0,0 +1,236 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef String16STL_h
+#define String16STL_h
+
+#include <stdint.h>
+
+#include <cstdlib>
+#include <cstring>
+#include <string>
+#include <vector>
+
+using UChar = uint16_t;
+using UChar32 = uint32_t;
+using LChar = unsigned char;
+// presubmit: allow wstring
+using wstring = std::basic_string<UChar>;
+const size_t kNotFound = static_cast<size_t>(-1);
+
+namespace blink {
+namespace protocol {
+
+class String16 {
+public:
+ String16() { }
+ String16(const String16& other) : m_impl(other.m_impl) { }
+ // presubmit: allow wstring
+ String16(const wstring& impl) : m_impl(impl) { }
+ String16(const UChar* characters) : m_impl(characters) { }
+ String16(const char* characters) : String16(characters, std::strlen(characters)) { }
+ String16(const char* characters, size_t size)
+ {
+ m_impl.resize(size);
+ for (size_t i = 0; i < size; ++i)
+ m_impl[i] = characters[i];
+ }
+ String16(const UChar* characters, size_t size) : m_impl(characters, size) { }
+
+ unsigned sizeInBytes() const { return m_impl.size() * sizeof(UChar); }
+ const UChar* characters16() const { return m_impl.c_str(); }
+ std::string utf8() const;
+ static String16 fromUTF8(const char* stringStart, size_t length);
+ static String16 number(int i) { return String16(String16::intToString(i).c_str()); }
+ static String16 fromDouble(double d) { return String16(String16::doubleToString(d).c_str()); }
+ static String16 fromDoubleFixedPrecision(double d, int len) { return String16(String16::doubleToString(d).c_str()); }
+
+ static double charactersToDouble(const UChar* characters, size_t length, bool* ok = 0)
+ {
+ std::string str;
+ str.resize(length);
+ for (size_t i = 0; i < length; ++i)
+ str[i] = static_cast<char>(characters[i]);
+
+ const char* buffer = str.c_str();
+ char* endptr;
+ double result = strtod(buffer, &endptr);
+ if (ok)
+ *ok = buffer + length == endptr;
+ return result;
+ }
+
+ String16 substring(unsigned pos, unsigned len = 0xFFFFFFFF) const
+ {
+ return String16(m_impl.substr(pos, len));
+ }
+
+ String16 stripWhiteSpace() const;
+
+ int toInt(bool* ok = 0) const
+ {
+ size_t length = m_impl.length();
+ std::string str;
+ str.resize(length);
+ for (size_t i = 0; i < length; ++i)
+ str[i] = static_cast<char>(m_impl[i]);
+
+ const char* buffer = str.c_str();
+ char* endptr;
+ int result = strtol(buffer, &endptr, 10);
+ if (ok)
+ *ok = buffer + length == endptr;
+ return result;
+ }
+
+ size_t length() const { return m_impl.length(); }
+ bool isEmpty() const { return !m_impl.length(); }
+ UChar operator[](unsigned index) const { return m_impl[index]; }
+
+ size_t find(UChar c, unsigned start = 0) const
+ {
+ return m_impl.find(c, start);
+ }
+
+ size_t find(const String16& str, unsigned start = 0) const
+ {
+ return m_impl.find(str.m_impl, start);
+ }
+
+ size_t reverseFind(const String16& str, unsigned start = 0xFFFFFFFF) const
+ {
+ return m_impl.rfind(str.m_impl, start);
+ }
+
+ bool endsWith(UChar character) const
+ {
+ return m_impl.length() && m_impl[m_impl.length() - 1] == character;
+ }
+
+ // presubmit: allow wstring
+ const wstring& impl() const { return m_impl; }
+
+ std::size_t hash() const
+ {
+ if (!has_hash) {
+ size_t hash = 0;
+ for (size_t i = 0; i < length(); ++i)
+ hash = 31 * hash + m_impl[i];
+ hash_code = hash;
+ has_hash = true;
+ }
+ return hash_code;
+ }
+
+private:
+ static std::string intToString(int i);
+ static std::string doubleToString(double d);
+ // presubmit: allow wstring
+ wstring m_impl;
+ mutable bool has_hash = false;
+ mutable std::size_t hash_code;
+};
+
+static inline bool isSpaceOrNewline(UChar c)
+{
+ return false;
+}
+
+class String16Builder {
+public:
+ String16Builder() { }
+
+ void append(const String16& str)
+ {
+ m_impl += str.impl();
+ }
+
+ void append(UChar c)
+ {
+ m_impl += c;
+ }
+
+ void append(LChar c)
+ {
+ m_impl += c;
+ }
+
+ void append(char c)
+ {
+ m_impl += c;
+ }
+
+ void appendNumber(int i)
+ {
+ m_impl = m_impl + String16::number(i).impl();
+ }
+
+ void append(const UChar* c, size_t length)
+ {
+ // presubmit: allow wstring
+ m_impl += wstring(c, length);
+ }
+
+ void append(const char* c, size_t length)
+ {
+ m_impl += String16(c, length).impl();
+ }
+
+ String16 toString()
+ {
+ return String16(m_impl);
+ }
+
+ void reserveCapacity(unsigned newCapacity)
+ {
+ }
+
+private:
+ // presubmit: allow wstring
+ wstring m_impl;
+};
+
+inline bool operator==(const String16& a, const String16& b) { return a.impl() == b.impl(); }
+inline bool operator!=(const String16& a, const String16& b) { return a.impl() != b.impl(); }
+inline bool operator==(const String16& a, const char* b) { return a.impl() == String16(b).impl(); }
+inline bool operator<(const String16& a, const String16& b) { return a.impl() < b.impl(); }
+
+inline String16 operator+(const String16& a, const char* b)
+{
+ return String16(a.impl() + String16(b).impl());
+}
+
+inline String16 operator+(const char* a, const String16& b)
+{
+ return String16(String16(a).impl() + b.impl());
+}
+
+inline String16 operator+(const String16& a, const String16& b)
+{
+ return String16(a.impl() + b.impl());
+}
+
+} // namespace protocol
+} // namespace blink
+
+using String16 = blink::protocol::String16;
+using String16Builder = blink::protocol::String16Builder;
+
+
+namespace WTF {
+// Interim solution for those headers that reference WTF::String for overrides.
+// It does nothing. If the code actually relies on WTF:String, it will not
+// compile!
+// TODO(eostroukhov): Eradicate
+class String {
+public:
+ String() {};
+ String(const String16& other) {};
+ operator String16() const { return String16(); };
+};
+} // namespace WTF
+
+using String = WTF::String;
+
+#endif // !defined(String16STL_h)
diff --git a/deps/v8_inspector/platform/inspector_protocol/String16WTF.cpp b/deps/v8_inspector/platform/inspector_protocol/String16WTF.cpp
new file mode 100644
index 0000000000..387ecc3f48
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/String16WTF.cpp
@@ -0,0 +1,47 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/inspector_protocol/String16WTF.h"
+
+namespace blink {
+namespace protocol {
+
+String16::String16(const String16& other) : m_impl(other.m_impl) { }
+
+String16::String16(const UChar* u, unsigned length) : m_impl(u, length) { }
+
+String16::String16(const char* characters) : String16(characters, strlen(characters)) { }
+
+String16::String16(const WTF::String& other)
+{
+ if (other.isNull())
+ return;
+ if (!other.is8Bit()) {
+ m_impl = other;
+ return;
+ }
+
+ UChar* data;
+ const LChar* characters = other.characters8();
+ size_t length = other.length();
+ m_impl = String::createUninitialized(length, data);
+ for (size_t i = 0; i < length; ++i)
+ data[i] = characters[i];
+}
+
+String16::String16(const char* characters, size_t length)
+{
+ UChar* data;
+ m_impl = String::createUninitialized(length, data);
+ for (size_t i = 0; i < length; ++i)
+ data[i] = characters[i];
+}
+
+String16 String16::createUninitialized(unsigned length, UChar*& data)
+{
+ return String::createUninitialized(length, data);
+}
+
+} // namespace protocol
+} // namespace blink
diff --git a/deps/v8_inspector/platform/inspector_protocol/String16WTF.h b/deps/v8_inspector/platform/inspector_protocol/String16WTF.h
new file mode 100644
index 0000000000..4ee9c8df52
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/String16WTF.h
@@ -0,0 +1,139 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef String16WTF_h
+#define String16WTF_h
+
+#include "platform/Decimal.h"
+#include "public/platform/WebString.h"
+#include "wtf/text/StringBuilder.h"
+#include "wtf/text/StringConcatenate.h"
+#include "wtf/text/StringHash.h"
+#include "wtf/text/WTFString.h"
+
+namespace blink {
+namespace protocol {
+
+class PLATFORM_EXPORT String16 {
+public:
+ String16() { }
+ String16(const String16& other);
+ String16(const UChar*, unsigned);
+ String16(const char*);
+ String16(const char*, size_t);
+ static String16 createUninitialized(unsigned length, UChar*& data);
+
+ // WTF convenience constructors and helper methods.
+ String16(const WebString& other) : String16(String(other)) { }
+ template<typename StringType1, typename StringType2>
+ String16(const WTF::StringAppend<StringType1, StringType2>& impl) : String16(String(impl)) { }
+ String16(const WTF::AtomicString& impl) : String16(String(impl)) { }
+ String16(const WTF::String& impl);
+ String16(WTF::HashTableDeletedValueType) : m_impl(WTF::HashTableDeletedValue) { }
+ bool isHashTableDeletedValue() const { return m_impl.isHashTableDeletedValue(); }
+ operator WTF::String() const { return m_impl; }
+ operator WebString() { return m_impl; }
+ const WTF::String& impl() const { return m_impl; }
+
+ ~String16() { }
+
+ static String16 number(int i) { return String::number(i); }
+ static String16 fromDouble(double number) { return Decimal::fromDouble(number).toString(); }
+ static String16 fromDoubleFixedPrecision(double number, int precision) { return String::numberToStringFixedWidth(number, precision); }
+
+ size_t length() const { return m_impl.length(); }
+ bool isEmpty() const { return m_impl.isEmpty(); }
+ UChar operator[](unsigned index) const { return m_impl[index]; }
+
+ unsigned sizeInBytes() const { return m_impl.sizeInBytes(); }
+ const UChar* characters16() const { return m_impl.isEmpty() ? nullptr : m_impl.characters16(); }
+
+ static double charactersToDouble(const LChar* characters, size_t length, bool* ok = 0) { return ::charactersToDouble(characters, length, ok); }
+ static double charactersToDouble(const UChar* characters, size_t length, bool* ok = 0) { return ::charactersToDouble(characters, length, ok); }
+
+ String16 substring(unsigned pos, unsigned len = UINT_MAX) const { return m_impl.substring(pos, len); }
+ String16 stripWhiteSpace() const { return m_impl.stripWhiteSpace(); }
+
+ int toInt(bool* ok = 0) const { return m_impl.toInt(ok); }
+
+ size_t find(UChar c, unsigned start = 0) const { return m_impl.find(c, start); }
+ size_t find(const String16& str, unsigned start = 0) const { return m_impl.find(str.impl(), start); }
+ size_t reverseFind(const String16& str, unsigned start = UINT_MAX) const { return m_impl.reverseFind(str.impl(), start); }
+
+ bool startWith(const String16& s) const { return m_impl.startsWith(s); }
+ bool startWith(UChar character) const { return m_impl.startsWith(character); }
+ bool endsWith(const String16& s) const { return m_impl.endsWith(s); }
+ bool endsWith(UChar character) const { return m_impl.endsWith(character); }
+
+private:
+ WTF::String m_impl;
+};
+
+class String16Builder {
+public:
+ String16Builder() { }
+ void append(const String16& str) { m_impl.append(str); };
+ void append(UChar c) { m_impl.append(c); };
+ void append(LChar c) { m_impl.append(c); };
+ void append(char c) { m_impl.append(c); };
+ void append(const UChar* c, size_t size) { m_impl.append(c, size); };
+ void append(const char* characters, unsigned length) { m_impl.append(characters, length); }
+ void appendNumber(int number) { m_impl.appendNumber(number); }
+ String16 toString() { return m_impl.toString(); }
+ void reserveCapacity(unsigned newCapacity) { m_impl.reserveCapacity(newCapacity); }
+
+private:
+ WTF::StringBuilder m_impl;
+};
+
+inline bool operator==(const String16& a, const String16& b) { return a.impl() == b.impl(); }
+inline bool operator!=(const String16& a, const String16& b) { return a.impl() != b.impl(); }
+inline bool operator==(const String16& a, const char* b) { return a.impl() == b; }
+
+inline String16 operator+(const String16& a, const char* b)
+{
+ return String(a.impl() + b);
+}
+
+inline String16 operator+(const char* a, const String16& b)
+{
+ return String(a + b.impl());
+}
+
+inline String16 operator+(const String16& a, const String16& b)
+{
+ return String(a.impl() + b.impl());
+}
+
+} // namespace protocol
+} // namespace blink
+
+using String16 = blink::protocol::String16;
+using String16Builder = blink::protocol::String16Builder;
+
+namespace WTF {
+
+struct String16Hash {
+ static unsigned hash(const String16& key) { return StringHash::hash(key.impl()); }
+ static bool equal(const String16& a, const String16& b)
+ {
+ return StringHash::equal(a.impl(), b.impl());
+ }
+ static const bool safeToCompareToEmptyOrDeleted = false;
+};
+
+template<typename T> struct DefaultHash;
+template<> struct DefaultHash<String16> {
+ typedef String16Hash Hash;
+};
+
+template<>
+struct HashTraits<String16> : SimpleClassHashTraits<String16> {
+ static const bool hasIsEmptyValueFunction = true;
+ static bool isEmptyValue(const String16& a) { return a.impl().isNull(); }
+};
+
+} // namespace WTF
+
+#endif // !defined(String16WTF_h)
diff --git a/deps/v8_inspector/platform/inspector_protocol/TypeBuilder_cpp.template b/deps/v8_inspector/platform/inspector_protocol/TypeBuilder_cpp.template
new file mode 100644
index 0000000000..d80473a9b7
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/TypeBuilder_cpp.template
@@ -0,0 +1,130 @@
+// This file is generated
+
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/inspector_protocol/{{class_name}}.h"
+
+namespace blink {
+namespace protocol {
+
+std::unique_ptr<Object> Object::parse(protocol::Value* value, ErrorSupport* errors)
+{
+ protocol::DictionaryValue* object = DictionaryValue::cast(value);
+ if (!object) {
+ errors->addError("object expected");
+ return nullptr;
+ }
+ return wrapUnique(new Object(wrapUnique(static_cast<DictionaryValue*>(object->clone().release()))));
+}
+
+std::unique_ptr<protocol::DictionaryValue> Object::serialize() const
+{
+ return DictionaryValue::cast(m_object->clone());
+}
+
+std::unique_ptr<Object> Object::clone() const
+{
+ return wrapUnique(new Object(DictionaryValue::cast(m_object->clone())));
+}
+
+Object::Object(std::unique_ptr<protocol::DictionaryValue> object) : m_object(std::move(object)) { }
+Object::~Object() { }
+
+// ------------- Enum values from types.
+{% for domain in api.domains %}
+
+namespace {{domain.domain}} {
+ {% for type in domain.types %}
+ {% if "enum" in type %}
+
+namespace {{type.id}}Enum {
+ {% for literal in type.enum %}
+const char* {{ literal | dash_to_camelcase}} = "{{literal}}";
+ {% endfor %}
+} // {{type.id}}Enum
+ {% endif %}
+ {% for property in type.properties %}
+ {% if "enum" in property %}
+
+ {% for literal in property.enum %}
+const char* {{type.id}}::{{property.name | to_title_case}}Enum::{{ literal | dash_to_camelcase}} = "{{literal}}";
+ {% endfor %}
+ {% endif %}
+ {% endfor %}
+ {% if not (type.type == "object") or not ("properties" in type) %}{% continue %}{% endif %}
+
+std::unique_ptr<{{type.id}}> {{type.id}}::parse(protocol::Value* value, ErrorSupport* errors)
+{
+ if (!value || value->type() != protocol::Value::TypeObject) {
+ errors->addError("object expected");
+ return nullptr;
+ }
+
+ std::unique_ptr<{{type.id}}> result(new {{type.id}}());
+ protocol::DictionaryValue* object = DictionaryValue::cast(value);
+ errors->push();
+ {% for property in type.properties %}
+ protocol::Value* {{property.name}}Value = object->get("{{property.name}}");
+ {% if property.optional %}
+ if ({{property.name}}Value) {
+ errors->setName("{{property.name}}");
+ result->m_{{property.name}} = FromValue<{{resolve_type(property).raw_type}}>::parse({{property.name}}Value, errors);
+ }
+ {% else %}
+ errors->setName("{{property.name}}");
+ result->m_{{property.name}} = FromValue<{{resolve_type(property).raw_type}}>::parse({{property.name}}Value, errors);
+ {% endif %}
+ {% endfor %}
+ errors->pop();
+ if (errors->hasErrors())
+ return nullptr;
+ return result;
+}
+
+std::unique_ptr<protocol::DictionaryValue> {{type.id}}::serialize() const
+{
+ std::unique_ptr<protocol::DictionaryValue> result = DictionaryValue::create();
+ {% for property in type.properties %}
+ {% if property.optional %}
+ if (m_{{property.name}}.isJust())
+ result->setValue("{{property.name}}", toValue(m_{{property.name}}.fromJust()));
+ {% else %}
+ result->setValue("{{property.name}}", toValue({{resolve_type(property).to_raw_type % ("m_" + property.name)}}));
+ {% endif %}
+ {% endfor %}
+ return result;
+}
+
+std::unique_ptr<{{type.id}}> {{type.id}}::clone() const
+{
+ ErrorSupport errors;
+ return parse(serialize().get(), &errors);
+}
+ {% endfor %}
+} // {{domain.domain}}
+{% endfor %}
+
+// ------------- Enum values from params.
+{% for domain in api.domains %}
+ {% for command in join_arrays(domain, ["commands", "events"]) %}
+ {% for param in join_arrays(command, ["parameters", "returns"]) %}
+ {% if "enum" in param %}
+
+namespace {{domain.domain}} {
+namespace {{command.name | to_title_case}} {
+namespace {{param.name | to_title_case}}Enum {
+ {% for literal in param.enum %}
+const char* {{ literal | to_title_case}} = "{{literal}}";
+ {% endfor %}
+} // {{param.name | to_title_case}}Enum
+} // {{command.name | to_title_case }}
+} // {{domain.domain}}
+ {% endif %}
+ {% endfor %}
+ {% endfor %}
+{% endfor %}
+
+} // namespace protocol
+} // namespace blink
diff --git a/deps/v8_inspector/platform/inspector_protocol/TypeBuilder_h.template b/deps/v8_inspector/platform/inspector_protocol/TypeBuilder_h.template
new file mode 100644
index 0000000000..75f6704328
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/TypeBuilder_h.template
@@ -0,0 +1,211 @@
+// This file is generated
+
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef {{class_name}}_h
+#define {{class_name}}_h
+
+#include "platform/PlatformExport.h"
+#include "platform/inspector_protocol/Array.h"
+#include "platform/inspector_protocol/ErrorSupport.h"
+#include "platform/inspector_protocol/Maybe.h"
+#include "platform/inspector_protocol/String16.h"
+#include "platform/inspector_protocol/Values.h"
+#include "platform/inspector_protocol/ValueConversions.h"
+#include "wtf/Assertions.h"
+#include "wtf/PtrUtil.h"
+
+namespace blink {
+namespace protocol {
+
+using ErrorString = String16;
+
+class PLATFORM_EXPORT Object {
+public:
+ static std::unique_ptr<Object> parse(protocol::Value* value, ErrorSupport* errors);
+ ~Object();
+
+ std::unique_ptr<protocol::DictionaryValue> serialize() const;
+ std::unique_ptr<Object> clone() const;
+private:
+ Object(std::unique_ptr<protocol::DictionaryValue> object);
+ std::unique_ptr<protocol::DictionaryValue> m_object;
+};
+
+{% for domain in api.domains %}
+
+// ------------- Forward declarations and typedefs.
+
+namespace {{domain.domain}} {
+ {% for type in domain.types %}
+ {% if type.type == "object" %}
+ {% if "properties" in type %}
+// {{type.description}}
+class {{type.id}};
+ {% else %}
+// {{type.description}}
+using {{type.id}} = Object;
+ {% endif %}
+ {% elif type.type != "array" %}
+// {{type.description}}
+using {{type.id}} = {{resolve_type(type).type}};
+ {% endif %}
+ {% endfor %}
+} // {{domain.domain}}
+{% endfor %}
+
+// ------------- Enum values from types.
+{% for domain in api.domains %}
+ {% for type in domain.types %}
+ {% if "enum" in type %}
+
+namespace {{domain.domain}} {
+namespace {{type.id}}Enum {
+ {% for literal in type.enum %}
+PLATFORM_EXPORT extern const char* {{ literal | dash_to_camelcase}};
+ {% endfor %}
+} // {{type.id}}Enum
+} // {{domain.domain}}
+ {% endif %}
+ {% endfor %}
+{% endfor %}
+
+// ------------- Enum values from params.
+{% for domain in api.domains %}
+ {% for command in join_arrays(domain, ["commands", "events"]) %}
+ {% for param in join_arrays(command, ["parameters", "returns"]) %}
+ {% if "enum" in param %}
+
+namespace {{domain.domain}} {
+namespace {{command.name | to_title_case}} {
+namespace {{param.name | to_title_case}}Enum {
+ {% for literal in param.enum %}
+PLATFORM_EXPORT extern const char* {{ literal | dash_to_camelcase}};
+ {% endfor %}
+} // {{param.name | to_title_case}}Enum
+} // {{command.name | to_title_case }}
+} // {{domain.domain}}
+ {% endif %}
+ {% endfor %}
+ {% endfor %}
+{% endfor %}
+
+// ------------- Type and builder declarations.
+{% for domain in api.domains %}
+
+namespace {{domain.domain}} {
+ {% for type in domain.types %}
+ {% if not (type.type == "object") or not ("properties" in type) %}{% continue %}{% endif %}
+ {% set type_def = type_definition(domain.domain + "." + type.id)%}
+
+// {{type.description}}
+class PLATFORM_EXPORT {{type.id}} {
+public:
+ static std::unique_ptr<{{type.id}}> parse(protocol::Value* value, ErrorSupport* errors);
+
+ ~{{type.id}}() { }
+ {% for property in type.properties %}
+ {% if "enum" in property %}
+
+ struct PLATFORM_EXPORT {{property.name | to_title_case}}Enum {
+ {% for literal in property.enum %}
+ static const char* {{ literal | dash_to_camelcase}};
+ {% endfor %}
+ }; // {{property.name | to_title_case}}Enum
+ {% endif %}
+
+ {% if property.optional %}
+ bool has{{property.name | to_title_case}}() { return m_{{property.name}}.isJust(); }
+ {{resolve_type(property).raw_return_type}} get{{property.name | to_title_case}}({{resolve_type(property).raw_pass_type}} defaultValue) { return m_{{property.name}}.isJust() ? m_{{property.name}}.fromJust() : defaultValue; }
+ {% else %}
+ {{resolve_type(property).raw_return_type}} get{{property.name | to_title_case}}() { return {{resolve_type(property).to_raw_type % ("m_" + property.name)}}; }
+ {% endif %}
+ void set{{property.name | to_title_case}}({{resolve_type(property).pass_type}} value) { m_{{property.name}} = {{resolve_type(property).to_rvalue % "value"}}; }
+ {% endfor %}
+
+ std::unique_ptr<protocol::DictionaryValue> serialize() const;
+ std::unique_ptr<{{type.id}}> clone() const;
+
+ template<int STATE>
+ class {{type.id}}Builder {
+ public:
+ enum {
+ NoFieldsSet = 0,
+ {% set count = 0 %}
+ {% for property in type.properties %}
+ {% if not(property.optional) %}
+ {% set count = count + 1 %}
+ {{property.name | to_title_case}}Set = 1 << {{count}},
+ {% endif %}
+ {% endfor %}
+ AllFieldsSet = (
+ {%- for property in type.properties %}
+ {% if not(property.optional) %}{{property.name | to_title_case}}Set | {%endif %}
+ {% endfor %}0)};
+
+ {% for property in type.properties %}
+
+ {% if property.optional %}
+ {{type.id}}Builder<STATE>& set{{property.name | to_title_case}}({{resolve_type(property).pass_type}} value)
+ {
+ m_result->set{{property.name | to_title_case}}({{resolve_type(property).to_rvalue % "value"}});
+ return *this;
+ }
+ {% else %}
+ {{type.id}}Builder<STATE | {{property.name | to_title_case}}Set>& set{{property.name | to_title_case}}({{resolve_type(property).pass_type}} value)
+ {
+ static_assert(!(STATE & {{property.name | to_title_case}}Set), "property {{property.name}} should not be set yet");
+ m_result->set{{property.name | to_title_case}}({{resolve_type(property).to_rvalue % "value"}});
+ return castState<{{property.name | to_title_case}}Set>();
+ }
+ {% endif %}
+ {% endfor %}
+
+ std::unique_ptr<{{type.id}}> build()
+ {
+ static_assert(STATE == AllFieldsSet, "state should be AllFieldsSet");
+ return std::move(m_result);
+ }
+
+ private:
+ friend class {{type.id}};
+ {{type.id}}Builder() : m_result(new {{type.id}}()) { }
+
+ template<int STEP> {{type.id}}Builder<STATE | STEP>& castState()
+ {
+ return *reinterpret_cast<{{type.id}}Builder<STATE | STEP>*>(this);
+ }
+
+ {{type_def.type}} m_result;
+ };
+
+ static {{type.id}}Builder<0> create()
+ {
+ return {{type.id}}Builder<0>();
+ }
+
+private:
+ {{type.id}}() { }
+
+ {% for property in type.properties %}
+ {% if property.optional %}
+ Maybe<{{resolve_type(property).raw_type}}> m_{{property.name}};
+ {% else %}
+ {{resolve_type(property).type}} m_{{property.name}};
+ {% endif %}
+ {% endfor %}
+};
+
+ {% endfor %}
+
+} // {{domain.domain}}
+{% endfor %}
+
+} // namespace protocol
+} // namespace blink
+
+using blink::protocol::ErrorString;
+
+#endif // !defined({{class_name}}_h)
diff --git a/deps/v8_inspector/platform/inspector_protocol/ValueConversions.cpp b/deps/v8_inspector/platform/inspector_protocol/ValueConversions.cpp
new file mode 100644
index 0000000000..98b8e7f5df
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/ValueConversions.cpp
@@ -0,0 +1,51 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/inspector_protocol/ValueConversions.h"
+
+namespace blink {
+namespace protocol {
+
+std::unique_ptr<protocol::Value> toValue(int value)
+{
+ return FundamentalValue::create(value);
+}
+
+std::unique_ptr<protocol::Value> toValue(double value)
+{
+ return FundamentalValue::create(value);
+}
+
+std::unique_ptr<protocol::Value> toValue(bool value)
+{
+ return FundamentalValue::create(value);
+}
+
+std::unique_ptr<protocol::Value> toValue(const String16& param)
+{
+ return StringValue::create(param);
+}
+
+std::unique_ptr<protocol::Value> toValue(const String& param)
+{
+ return StringValue::create(param);
+}
+
+std::unique_ptr<protocol::Value> toValue(Value* param)
+{
+ return param->clone();
+}
+
+std::unique_ptr<protocol::Value> toValue(DictionaryValue* param)
+{
+ return param->clone();
+}
+
+std::unique_ptr<protocol::Value> toValue(ListValue* param)
+{
+ return param->clone();
+}
+
+} // namespace protocol
+} // namespace blink
diff --git a/deps/v8_inspector/platform/inspector_protocol/ValueConversions.h b/deps/v8_inspector/platform/inspector_protocol/ValueConversions.h
new file mode 100644
index 0000000000..4a5066c928
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/ValueConversions.h
@@ -0,0 +1,163 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ValueConversions_h
+#define ValueConversions_h
+
+#include "platform/PlatformExport.h"
+#include "platform/inspector_protocol/ErrorSupport.h"
+#include "platform/inspector_protocol/String16.h"
+#include "platform/inspector_protocol/Values.h"
+
+namespace blink {
+namespace protocol {
+
+PLATFORM_EXPORT std::unique_ptr<protocol::Value> toValue(int value);
+
+PLATFORM_EXPORT std::unique_ptr<protocol::Value> toValue(double value);
+
+PLATFORM_EXPORT std::unique_ptr<protocol::Value> toValue(bool value);
+
+PLATFORM_EXPORT std::unique_ptr<protocol::Value> toValue(const String16& param);
+
+PLATFORM_EXPORT std::unique_ptr<protocol::Value> toValue(const String& param);
+
+PLATFORM_EXPORT std::unique_ptr<protocol::Value> toValue(protocol::Value* param);
+
+PLATFORM_EXPORT std::unique_ptr<protocol::Value> toValue(protocol::DictionaryValue* param);
+
+PLATFORM_EXPORT std::unique_ptr<protocol::Value> toValue(protocol::ListValue* param);
+
+template<typename T> std::unique_ptr<protocol::Value> toValue(T* param)
+{
+ return param->serialize();
+}
+
+template<typename T> std::unique_ptr<protocol::Value> toValue(const std::unique_ptr<T>& param)
+{
+ static_assert(sizeof(T) == 0, "use raw pointer version.");
+ return nullptr;
+}
+
+template<typename T> std::unique_ptr<protocol::Value> toValue(std::unique_ptr<T> param)
+{
+ static_assert(sizeof(T) == 0, "use raw pointer version.");
+ return nullptr;
+}
+
+template<typename T>
+struct FromValue {
+ static std::unique_ptr<T> parse(protocol::Value* value, ErrorSupport* errors)
+ {
+ return T::parse(value, errors);
+ }
+};
+
+template<>
+struct FromValue<bool> {
+ static bool parse(protocol::Value* value, ErrorSupport* errors)
+ {
+ bool result = false;
+ bool success = value ? value->asBoolean(&result) : false;
+ if (!success)
+ errors->addError("boolean value expected");
+ return result;
+ }
+};
+
+template<>
+struct FromValue<int> {
+ static int parse(protocol::Value* value, ErrorSupport* errors)
+ {
+ int result = 0;
+ bool success = value ? value->asNumber(&result) : false;
+ if (!success)
+ errors->addError("integer value expected");
+ return result;
+ }
+};
+
+template<>
+struct FromValue<double> {
+ static double parse(protocol::Value* value, ErrorSupport* errors)
+ {
+ double result = 0;
+ bool success = value ? value->asNumber(&result) : false;
+ if (!success)
+ errors->addError("double value expected");
+ return result;
+ }
+};
+
+template<>
+struct FromValue<String> {
+ static String parse(protocol::Value* value, ErrorSupport* errors)
+ {
+ String16 result;
+ bool success = value ? value->asString(&result) : false;
+ if (!success)
+ errors->addError("string value expected");
+ return result;
+ }
+};
+
+template<>
+struct FromValue<String16> {
+ static String16 parse(protocol::Value* value, ErrorSupport* errors)
+ {
+ String16 result;
+ bool success = value ? value->asString(&result) : false;
+ if (!success)
+ errors->addError("string value expected");
+ return result;
+ }
+};
+
+template<>
+struct FromValue<Value> {
+ static std::unique_ptr<Value> parse(protocol::Value* value, ErrorSupport* errors)
+ {
+ bool success = !!value;
+ if (!success)
+ errors->addError("value expected");
+ return value->clone();
+ }
+};
+
+template<>
+struct FromValue<DictionaryValue> {
+ static std::unique_ptr<DictionaryValue> parse(protocol::Value* value, ErrorSupport* errors)
+ {
+ bool success = value && value->type() == protocol::Value::TypeObject;
+ if (!success)
+ errors->addError("object expected");
+ return DictionaryValue::cast(value->clone());
+ }
+};
+
+template<>
+struct FromValue<ListValue> {
+ static std::unique_ptr<ListValue> parse(protocol::Value* value, ErrorSupport* errors)
+ {
+ bool success = value && value->type() == protocol::Value::TypeArray;
+ if (!success)
+ errors->addError("list expected");
+ return ListValue::cast(value->clone());
+ }
+};
+
+template<typename T> class Array;
+
+template<typename T>
+struct FromValue<protocol::Array<T>> {
+ static std::unique_ptr<protocol::Array<T>> parse(protocol::Value* value, ErrorSupport* errors)
+ {
+ return protocol::Array<T>::parse(value, errors);
+ }
+};
+
+} // namespace platform
+} // namespace blink
+
+#endif // !defined(ValueConversions_h)
diff --git a/deps/v8_inspector/platform/inspector_protocol/Values.cpp b/deps/v8_inspector/platform/inspector_protocol/Values.cpp
new file mode 100644
index 0000000000..979e3d8b2b
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/Values.cpp
@@ -0,0 +1,354 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/inspector_protocol/Values.h"
+
+#include "platform/inspector_protocol/Parser.h"
+#include "platform/inspector_protocol/String16.h"
+#include "wtf/Assertions.h"
+#include <cmath>
+
+namespace blink {
+namespace protocol {
+
+namespace {
+
+const char* const nullString = "null";
+const char* const trueString = "true";
+const char* const falseString = "false";
+
+inline bool escapeChar(UChar c, String16Builder* dst)
+{
+ switch (c) {
+ case '\b': dst->append("\\b"); break;
+ case '\f': dst->append("\\f"); break;
+ case '\n': dst->append("\\n"); break;
+ case '\r': dst->append("\\r"); break;
+ case '\t': dst->append("\\t"); break;
+ case '\\': dst->append("\\\\"); break;
+ case '"': dst->append("\\\""); break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+const LChar hexDigits[17] = "0123456789ABCDEF";
+
+void appendUnsignedAsHex(UChar number, String16Builder* dst)
+{
+ dst->append("\\u");
+ for (size_t i = 0; i < 4; ++i) {
+ dst->append(hexDigits[(number & 0xF000) >> 12]);
+ number <<= 4;
+ }
+}
+
+void escapeStringForJSON(const String16& str, String16Builder* dst)
+{
+ for (unsigned i = 0; i < str.length(); ++i) {
+ UChar c = str[i];
+ if (!escapeChar(c, dst)) {
+ if (c < 32 || c > 126 || c == '<' || c == '>') {
+ // 1. Escaping <, > to prevent script execution.
+ // 2. Technically, we could also pass through c > 126 as UTF8, but this
+ // is also optional. It would also be a pain to implement here.
+ appendUnsignedAsHex(c, dst);
+ } else {
+ dst->append(c);
+ }
+ }
+ }
+}
+
+void doubleQuoteStringForJSON(const String16& str, String16Builder* dst)
+{
+ dst->append('"');
+ escapeStringForJSON(str, dst);
+ dst->append('"');
+}
+
+} // anonymous namespace
+
+bool Value::asBoolean(bool*) const
+{
+ return false;
+}
+
+bool Value::asNumber(double*) const
+{
+ return false;
+}
+
+bool Value::asNumber(int*) const
+{
+ return false;
+}
+
+bool Value::asString(String16*) const
+{
+ return false;
+}
+
+String16 Value::toJSONString() const
+{
+ String16Builder result;
+ result.reserveCapacity(512);
+ writeJSON(&result);
+ return result.toString();
+}
+
+void Value::writeJSON(String16Builder* output) const
+{
+ DCHECK(m_type == TypeNull);
+ output->append(nullString, 4);
+}
+
+std::unique_ptr<Value> Value::clone() const
+{
+ return Value::null();
+}
+
+bool FundamentalValue::asBoolean(bool* output) const
+{
+ if (type() != TypeBoolean)
+ return false;
+ *output = m_boolValue;
+ return true;
+}
+
+bool FundamentalValue::asNumber(double* output) const
+{
+ if (type() != TypeNumber)
+ return false;
+ *output = m_doubleValue;
+ return true;
+}
+
+bool FundamentalValue::asNumber(int* output) const
+{
+ if (type() != TypeNumber)
+ return false;
+ *output = static_cast<int>(m_doubleValue);
+ return true;
+}
+
+void FundamentalValue::writeJSON(String16Builder* output) const
+{
+ DCHECK(type() == TypeBoolean || type() == TypeNumber);
+ if (type() == TypeBoolean) {
+ if (m_boolValue)
+ output->append(trueString, 4);
+ else
+ output->append(falseString, 5);
+ } else if (type() == TypeNumber) {
+ if (!std::isfinite(m_doubleValue)) {
+ output->append(nullString, 4);
+ return;
+ }
+ output->append(String16::fromDouble(m_doubleValue));
+ }
+}
+
+std::unique_ptr<Value> FundamentalValue::clone() const
+{
+ return type() == TypeNumber ? FundamentalValue::create(m_doubleValue) : FundamentalValue::create(m_boolValue);
+}
+
+bool StringValue::asString(String16* output) const
+{
+ *output = m_stringValue;
+ return true;
+}
+
+void StringValue::writeJSON(String16Builder* output) const
+{
+ DCHECK(type() == TypeString);
+ doubleQuoteStringForJSON(m_stringValue, output);
+}
+
+std::unique_ptr<Value> StringValue::clone() const
+{
+ return StringValue::create(m_stringValue);
+}
+
+DictionaryValue::~DictionaryValue()
+{
+}
+
+void DictionaryValue::setBoolean(const String16& name, bool value)
+{
+ setValue(name, FundamentalValue::create(value));
+}
+
+void DictionaryValue::setNumber(const String16& name, double value)
+{
+ setValue(name, FundamentalValue::create(value));
+}
+
+void DictionaryValue::setString(const String16& name, const String16& value)
+{
+ setValue(name, StringValue::create(value));
+}
+
+void DictionaryValue::setValue(const String16& name, std::unique_ptr<Value> value)
+{
+ DCHECK(value);
+ if (m_data.set(name, std::move(value)))
+ m_order.append(name);
+}
+
+void DictionaryValue::setObject(const String16& name, std::unique_ptr<DictionaryValue> value)
+{
+ DCHECK(value);
+ if (m_data.set(name, std::move(value)))
+ m_order.append(name);
+}
+
+void DictionaryValue::setArray(const String16& name, std::unique_ptr<ListValue> value)
+{
+ DCHECK(value);
+ if (m_data.set(name, std::move(value)))
+ m_order.append(name);
+}
+
+bool DictionaryValue::getBoolean(const String16& name, bool* output) const
+{
+ protocol::Value* value = get(name);
+ if (!value)
+ return false;
+ return value->asBoolean(output);
+}
+
+bool DictionaryValue::getString(const String16& name, String16* output) const
+{
+ protocol::Value* value = get(name);
+ if (!value)
+ return false;
+ return value->asString(output);
+}
+
+DictionaryValue* DictionaryValue::getObject(const String16& name) const
+{
+ return DictionaryValue::cast(get(name));
+}
+
+protocol::ListValue* DictionaryValue::getArray(const String16& name) const
+{
+ return ListValue::cast(get(name));
+}
+
+protocol::Value* DictionaryValue::get(const String16& name) const
+{
+ Dictionary::const_iterator it = m_data.find(name);
+ if (it == m_data.end())
+ return nullptr;
+ return it->second;
+}
+
+DictionaryValue::Entry DictionaryValue::at(size_t index) const
+{
+ String16 key = m_order[index];
+ return std::make_pair(key, m_data.get(key));
+}
+
+bool DictionaryValue::booleanProperty(const String16& name, bool defaultValue) const
+{
+ bool result = defaultValue;
+ getBoolean(name, &result);
+ return result;
+}
+
+double DictionaryValue::numberProperty(const String16& name, double defaultValue) const
+{
+ double result = defaultValue;
+ getNumber(name, &result);
+ return result;
+}
+
+void DictionaryValue::remove(const String16& name)
+{
+ m_data.remove(name);
+ for (size_t i = 0; i < m_order.size(); ++i) {
+ if (m_order[i] == name) {
+ m_order.remove(i);
+ break;
+ }
+ }
+}
+
+void DictionaryValue::writeJSON(String16Builder* output) const
+{
+ output->append('{');
+ for (size_t i = 0; i < m_order.size(); ++i) {
+ Dictionary::const_iterator it = m_data.find(m_order[i]);
+ CHECK(it != m_data.end());
+ if (i)
+ output->append(',');
+ doubleQuoteStringForJSON(it->first, output);
+ output->append(':');
+ it->second->writeJSON(output);
+ }
+ output->append('}');
+}
+
+std::unique_ptr<Value> DictionaryValue::clone() const
+{
+ std::unique_ptr<DictionaryValue> result = DictionaryValue::create();
+ for (size_t i = 0; i < m_order.size(); ++i) {
+ String16 key = m_order[i];
+ Value* value = m_data.get(key);
+ DCHECK(value);
+ result->setValue(key, value->clone());
+ }
+ return std::move(result);
+}
+
+DictionaryValue::DictionaryValue()
+ : Value(TypeObject)
+{
+}
+
+ListValue::~ListValue()
+{
+}
+
+void ListValue::writeJSON(String16Builder* output) const
+{
+ output->append('[');
+ for (Vector<std::unique_ptr<protocol::Value>>::const_iterator it = m_data.begin(); it != m_data.end(); ++it) {
+ if (it != m_data.begin())
+ output->append(',');
+ (*it)->writeJSON(output);
+ }
+ output->append(']');
+}
+
+std::unique_ptr<Value> ListValue::clone() const
+{
+ std::unique_ptr<ListValue> result = ListValue::create();
+ for (Vector<std::unique_ptr<protocol::Value>>::const_iterator it = m_data.begin(); it != m_data.end(); ++it)
+ result->pushValue((*it)->clone());
+ return std::move(result);
+}
+
+ListValue::ListValue()
+ : Value(TypeArray)
+{
+}
+
+void ListValue::pushValue(std::unique_ptr<protocol::Value> value)
+{
+ DCHECK(value);
+ m_data.append(std::move(value));
+}
+
+protocol::Value* ListValue::at(size_t index)
+{
+ CHECK(index < m_data.size());
+ return m_data[index];
+}
+
+} // namespace protocol
+} // namespace blink
diff --git a/deps/v8_inspector/platform/inspector_protocol/Values.h b/deps/v8_inspector/platform/inspector_protocol/Values.h
new file mode 100644
index 0000000000..4202d33ec8
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/Values.h
@@ -0,0 +1,221 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef Values_h
+#define Values_h
+
+#include "platform/PlatformExport.h"
+#include "platform/inspector_protocol/Allocator.h"
+#include "platform/inspector_protocol/Collections.h"
+#include "platform/inspector_protocol/String16.h"
+#include "wtf/PtrUtil.h"
+
+namespace blink {
+namespace protocol {
+
+class ListValue;
+class DictionaryValue;
+class Value;
+
+class PLATFORM_EXPORT Value {
+ PROTOCOL_DISALLOW_COPY(Value);
+public:
+ static const int maxDepth = 1000;
+
+ virtual ~Value() { }
+
+ static std::unique_ptr<Value> null()
+ {
+ return std::unique_ptr<Value>(new Value());
+ }
+
+ enum ValueType {
+ TypeNull = 0,
+ TypeBoolean,
+ TypeNumber,
+ TypeString,
+ TypeObject,
+ TypeArray
+ };
+
+ ValueType type() const { return m_type; }
+
+ bool isNull() const { return m_type == TypeNull; }
+
+ virtual bool asBoolean(bool* output) const;
+ virtual bool asNumber(double* output) const;
+ virtual bool asNumber(int* output) const;
+ virtual bool asString(String16* output) const;
+
+ String16 toJSONString() const;
+ virtual void writeJSON(String16Builder* output) const;
+ virtual std::unique_ptr<Value> clone() const;
+
+protected:
+ Value() : m_type(TypeNull) { }
+ explicit Value(ValueType type) : m_type(type) { }
+
+private:
+ friend class DictionaryValue;
+ friend class ListValue;
+
+ ValueType m_type;
+};
+
+class PLATFORM_EXPORT FundamentalValue : public Value {
+public:
+ static std::unique_ptr<FundamentalValue> create(bool value)
+ {
+ return wrapUnique(new FundamentalValue(value));
+ }
+
+ static std::unique_ptr<FundamentalValue> create(int value)
+ {
+ return wrapUnique(new FundamentalValue(value));
+ }
+
+ static std::unique_ptr<FundamentalValue> create(double value)
+ {
+ return wrapUnique(new FundamentalValue(value));
+ }
+
+ bool asBoolean(bool* output) const override;
+ bool asNumber(double* output) const override;
+ bool asNumber(int* output) const override;
+ void writeJSON(String16Builder* output) const override;
+ std::unique_ptr<Value> clone() const override;
+
+private:
+ explicit FundamentalValue(bool value) : Value(TypeBoolean), m_boolValue(value) { }
+ explicit FundamentalValue(int value) : Value(TypeNumber), m_doubleValue((double)value) { }
+ explicit FundamentalValue(double value) : Value(TypeNumber), m_doubleValue(value) { }
+
+ union {
+ bool m_boolValue;
+ double m_doubleValue;
+ };
+};
+
+class PLATFORM_EXPORT StringValue : public Value {
+public:
+ static std::unique_ptr<StringValue> create(const String16& value)
+ {
+ return wrapUnique(new StringValue(value));
+ }
+
+ static std::unique_ptr<StringValue> create(const char* value)
+ {
+ return wrapUnique(new StringValue(value));
+ }
+
+ bool asString(String16* output) const override;
+ void writeJSON(String16Builder* output) const override;
+ std::unique_ptr<Value> clone() const override;
+
+private:
+ explicit StringValue(const String16& value) : Value(TypeString), m_stringValue(value) { }
+ explicit StringValue(const char* value) : Value(TypeString), m_stringValue(value) { }
+
+ String16 m_stringValue;
+};
+
+class PLATFORM_EXPORT DictionaryValue : public Value {
+public:
+ using Entry = std::pair<String16, Value*>;
+ static std::unique_ptr<DictionaryValue> create()
+ {
+ return wrapUnique(new DictionaryValue());
+ }
+
+ static DictionaryValue* cast(Value* value)
+ {
+ if (!value || value->type() != TypeObject)
+ return nullptr;
+ return static_cast<DictionaryValue*>(value);
+ }
+
+ static std::unique_ptr<DictionaryValue> cast(std::unique_ptr<Value> value)
+ {
+ return wrapUnique(DictionaryValue::cast(value.release()));
+ }
+
+ void writeJSON(String16Builder* output) const override;
+ std::unique_ptr<Value> clone() const override;
+
+ size_t size() const { return m_data.size(); }
+
+ void setBoolean(const String16& name, bool);
+ void setNumber(const String16& name, double);
+ void setString(const String16& name, const String16&);
+ void setValue(const String16& name, std::unique_ptr<Value>);
+ void setObject(const String16& name, std::unique_ptr<DictionaryValue>);
+ void setArray(const String16& name, std::unique_ptr<ListValue>);
+
+ bool getBoolean(const String16& name, bool* output) const;
+ template<class T> bool getNumber(const String16& name, T* output) const
+ {
+ Value* value = get(name);
+ if (!value)
+ return false;
+ return value->asNumber(output);
+ }
+ bool getString(const String16& name, String16* output) const;
+
+ DictionaryValue* getObject(const String16& name) const;
+ ListValue* getArray(const String16& name) const;
+ Value* get(const String16& name) const;
+ Entry at(size_t index) const;
+
+ bool booleanProperty(const String16& name, bool defaultValue) const;
+ double numberProperty(const String16& name, double defaultValue) const;
+ void remove(const String16& name);
+
+ ~DictionaryValue() override;
+
+private:
+ DictionaryValue();
+
+ using Dictionary = protocol::HashMap<String16, std::unique_ptr<Value>>;
+ Dictionary m_data;
+ protocol::Vector<String16> m_order;
+};
+
+class PLATFORM_EXPORT ListValue : public Value {
+public:
+ static std::unique_ptr<ListValue> create()
+ {
+ return wrapUnique(new ListValue());
+ }
+
+ static ListValue* cast(Value* value)
+ {
+ if (!value || value->type() != TypeArray)
+ return nullptr;
+ return static_cast<ListValue*>(value);
+ }
+
+ static std::unique_ptr<ListValue> cast(std::unique_ptr<Value> value)
+ {
+ return wrapUnique(ListValue::cast(value.release()));
+ }
+
+ ~ListValue() override;
+
+ void writeJSON(String16Builder* output) const override;
+ std::unique_ptr<Value> clone() const override;
+
+ void pushValue(std::unique_ptr<Value>);
+
+ Value* at(size_t index);
+ size_t size() const { return m_data.size(); }
+
+private:
+ ListValue();
+ protocol::Vector<std::unique_ptr<Value>> m_data;
+};
+
+} // namespace protocol
+} // namespace blink
+
+#endif // Values_h
diff --git a/deps/v8_inspector/platform/inspector_protocol/generate-inspector-protocol-version b/deps/v8_inspector/platform/inspector_protocol/generate-inspector-protocol-version
new file mode 100755
index 0000000000..514b6dfca4
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/generate-inspector-protocol-version
@@ -0,0 +1,464 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Inspector protocol validator.
+#
+# Tests that subsequent protocol changes are not breaking backwards compatibility.
+# Following violations are reported:
+#
+# - Domain has been removed
+# - Command has been removed
+# - Required command parameter was added or changed from optional
+# - Required response parameter was removed or changed to optional
+# - Event has been removed
+# - Required event parameter was removed or changed to optional
+# - Parameter type has changed.
+#
+# For the parameters with composite types the above checks are also applied
+# recursively to every property of the type.
+#
+# Adding --show_changes to the command line prints out a list of valid public API changes.
+
+import os.path
+import re
+import sys
+
+def list_to_map(items, key):
+ result = {}
+ for item in items:
+ if not "hidden" in item:
+ result[item[key]] = item
+ return result
+
+def named_list_to_map(container, name, key):
+ if name in container:
+ return list_to_map(container[name], key)
+ return {}
+
+def removed(reverse):
+ if reverse:
+ return "added"
+ return "removed"
+
+def required(reverse):
+ if reverse:
+ return "optional"
+ return "required"
+
+def compare_schemas(schema_1, schema_2, reverse):
+ errors = []
+ types_1 = normalize_types_in_schema(schema_1)
+ types_2 = normalize_types_in_schema(schema_2)
+
+ domains_by_name_1 = list_to_map(schema_1, "domain")
+ domains_by_name_2 = list_to_map(schema_2, "domain")
+
+ for name in domains_by_name_1:
+ domain_1 = domains_by_name_1[name]
+ if not name in domains_by_name_2:
+ errors.append("%s: domain has been %s" % (name, removed(reverse)))
+ continue
+ compare_domains(domain_1, domains_by_name_2[name], types_1, types_2, errors, reverse)
+ return errors
+
+def compare_domains(domain_1, domain_2, types_map_1, types_map_2, errors, reverse):
+ domain_name = domain_1["domain"]
+ commands_1 = named_list_to_map(domain_1, "commands", "name")
+ commands_2 = named_list_to_map(domain_2, "commands", "name")
+ for name in commands_1:
+ command_1 = commands_1[name]
+ if not name in commands_2:
+ errors.append("%s.%s: command has been %s" % (domain_1["domain"], name, removed(reverse)))
+ continue
+ compare_commands(domain_name, command_1, commands_2[name], types_map_1, types_map_2, errors, reverse)
+
+ events_1 = named_list_to_map(domain_1, "events", "name")
+ events_2 = named_list_to_map(domain_2, "events", "name")
+ for name in events_1:
+ event_1 = events_1[name]
+ if not name in events_2:
+ errors.append("%s.%s: event has been %s" % (domain_1["domain"], name, removed(reverse)))
+ continue
+ compare_events(domain_name, event_1, events_2[name], types_map_1, types_map_2, errors, reverse)
+
+def compare_commands(domain_name, command_1, command_2, types_map_1, types_map_2, errors, reverse):
+ context = domain_name + "." + command_1["name"]
+
+ params_1 = named_list_to_map(command_1, "parameters", "name")
+ params_2 = named_list_to_map(command_2, "parameters", "name")
+ # Note the reversed order: we allow removing but forbid adding parameters.
+ compare_params_list(context, "parameter", params_2, params_1, types_map_2, types_map_1, 0, errors, not reverse)
+
+ returns_1 = named_list_to_map(command_1, "returns", "name")
+ returns_2 = named_list_to_map(command_2, "returns", "name")
+ compare_params_list(context, "response parameter", returns_1, returns_2, types_map_1, types_map_2, 0, errors, reverse)
+
+def compare_events(domain_name, event_1, event_2, types_map_1, types_map_2, errors, reverse):
+ context = domain_name + "." + event_1["name"]
+ params_1 = named_list_to_map(event_1, "parameters", "name")
+ params_2 = named_list_to_map(event_2, "parameters", "name")
+ compare_params_list(context, "parameter", params_1, params_2, types_map_1, types_map_2, 0, errors, reverse)
+
+def compare_params_list(context, kind, params_1, params_2, types_map_1, types_map_2, depth, errors, reverse):
+ for name in params_1:
+ param_1 = params_1[name]
+ if not name in params_2:
+ if not "optional" in param_1:
+ errors.append("%s.%s: required %s has been %s" % (context, name, kind, removed(reverse)))
+ continue
+
+ param_2 = params_2[name]
+ if param_2 and "optional" in param_2 and not "optional" in param_1:
+ errors.append("%s.%s: %s %s is now %s" % (context, name, required(reverse), kind, required(not reverse)))
+ continue
+ type_1 = extract_type(param_1, types_map_1, errors)
+ type_2 = extract_type(param_2, types_map_2, errors)
+ compare_types(context + "." + name, kind, type_1, type_2, types_map_1, types_map_2, depth, errors, reverse)
+
+def compare_types(context, kind, type_1, type_2, types_map_1, types_map_2, depth, errors, reverse):
+ if depth > 10:
+ return
+
+ base_type_1 = type_1["type"]
+ base_type_2 = type_2["type"]
+
+ if base_type_1 != base_type_2:
+ errors.append("%s: %s base type mismatch, '%s' vs '%s'" % (context, kind, base_type_1, base_type_2))
+ elif base_type_1 == "object":
+ params_1 = named_list_to_map(type_1, "properties", "name")
+ params_2 = named_list_to_map(type_2, "properties", "name")
+ # If both parameters have the same named type use it in the context.
+ if "id" in type_1 and "id" in type_2 and type_1["id"] == type_2["id"]:
+ type_name = type_1["id"]
+ else:
+ type_name = "<object>"
+ context += " %s->%s" % (kind, type_name)
+ compare_params_list(context, "property", params_1, params_2, types_map_1, types_map_2, depth + 1, errors, reverse)
+ elif base_type_1 == "array":
+ item_type_1 = extract_type(type_1["items"], types_map_1, errors)
+ item_type_2 = extract_type(type_2["items"], types_map_2, errors)
+ compare_types(context, kind, item_type_1, item_type_2, types_map_1, types_map_2, depth + 1, errors, reverse)
+
+def extract_type(typed_object, types_map, errors):
+ if "type" in typed_object:
+ result = { "id": "<transient>", "type": typed_object["type"] }
+ if typed_object["type"] == "object":
+ result["properties"] = []
+ elif typed_object["type"] == "array":
+ result["items"] = typed_object["items"]
+ return result
+ elif "$ref" in typed_object:
+ ref = typed_object["$ref"]
+ if not ref in types_map:
+ errors.append("Can not resolve type: %s" % ref)
+ types_map[ref] = { "id": "<transient>", "type": "object" }
+ return types_map[ref]
+
+def normalize_types_in_schema(schema):
+ types = {}
+ for domain in schema:
+ domain_name = domain["domain"]
+ normalize_types(domain, domain_name, types)
+ return types
+
+def normalize_types(obj, domain_name, types):
+ if isinstance(obj, list):
+ for item in obj:
+ normalize_types(item, domain_name, types)
+ elif isinstance(obj, dict):
+ for key, value in obj.items():
+ if key == "$ref" and value.find(".") == -1:
+ obj[key] = "%s.%s" % (domain_name, value)
+ elif key == "id":
+ obj[key] = "%s.%s" % (domain_name, value)
+ types[obj[key]] = obj
+ else:
+ normalize_types(value, domain_name, types)
+
+def load_json(filename):
+ input_file = open(filename, "r")
+ json_string = input_file.read()
+ json_string = re.sub(":\s*true", ": True", json_string)
+ json_string = re.sub(":\s*false", ": False", json_string)
+ return eval(json_string)
+
+def self_test():
+ def create_test_schema_1():
+ return [
+ {
+ "domain": "Network",
+ "types": [
+ {
+ "id": "LoaderId",
+ "type": "string"
+ },
+ {
+ "id": "Headers",
+ "type": "object"
+ },
+ {
+ "id": "Request",
+ "type": "object",
+ "properties": [
+ { "name": "url", "type": "string" },
+ { "name": "method", "type": "string" },
+ { "name": "headers", "$ref": "Headers" },
+ { "name": "becameOptionalField", "type": "string" },
+ { "name": "removedField", "type": "string" },
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "removedCommand",
+ },
+ {
+ "name": "setExtraHTTPHeaders",
+ "parameters": [
+ { "name": "headers", "$ref": "Headers" },
+ { "name": "mismatched", "type": "string" },
+ { "name": "becameOptional", "$ref": "Headers" },
+ { "name": "removedRequired", "$ref": "Headers" },
+ { "name": "becameRequired", "$ref": "Headers", "optional": True },
+ { "name": "removedOptional", "$ref": "Headers", "optional": True },
+ ],
+ "returns": [
+ { "name": "mimeType", "type": "string" },
+ { "name": "becameOptional", "type": "string" },
+ { "name": "removedRequired", "type": "string" },
+ { "name": "becameRequired", "type": "string", "optional": True },
+ { "name": "removedOptional", "type": "string", "optional": True },
+ ]
+ }
+ ],
+ "events": [
+ {
+ "name": "requestWillBeSent",
+ "parameters": [
+ { "name": "frameId", "type": "string", "hidden": True },
+ { "name": "request", "$ref": "Request" },
+ { "name": "becameOptional", "type": "string" },
+ { "name": "removedRequired", "type": "string" },
+ { "name": "becameRequired", "type": "string", "optional": True },
+ { "name": "removedOptional", "type": "string", "optional": True },
+ ]
+ },
+ {
+ "name": "removedEvent",
+ "parameters": [
+ { "name": "errorText", "type": "string" },
+ { "name": "canceled", "type": "boolean", "optional": True }
+ ]
+ }
+ ]
+ },
+ {
+ "domain": "removedDomain"
+ }
+ ]
+
+ def create_test_schema_2():
+ return [
+ {
+ "domain": "Network",
+ "types": [
+ {
+ "id": "LoaderId",
+ "type": "string"
+ },
+ {
+ "id": "Request",
+ "type": "object",
+ "properties": [
+ { "name": "url", "type": "string" },
+ { "name": "method", "type": "string" },
+ { "name": "headers", "type": "object" },
+ { "name": "becameOptionalField", "type": "string", "optional": True },
+ ]
+ }
+ ],
+ "commands": [
+ {
+ "name": "addedCommand",
+ },
+ {
+ "name": "setExtraHTTPHeaders",
+ "parameters": [
+ { "name": "headers", "type": "object" },
+ { "name": "mismatched", "type": "object" },
+ { "name": "becameOptional", "type": "object" , "optional": True },
+ { "name": "addedRequired", "type": "object" },
+ { "name": "becameRequired", "type": "object" },
+ { "name": "addedOptional", "type": "object", "optional": True },
+ ],
+ "returns": [
+ { "name": "mimeType", "type": "string" },
+ { "name": "becameOptional", "type": "string", "optional": True },
+ { "name": "addedRequired", "type": "string"},
+ { "name": "becameRequired", "type": "string" },
+ { "name": "addedOptional", "type": "string", "optional": True },
+ ]
+ }
+ ],
+ "events": [
+ {
+ "name": "requestWillBeSent",
+ "parameters": [
+ { "name": "request", "$ref": "Request" },
+ { "name": "becameOptional", "type": "string", "optional": True },
+ { "name": "addedRequired", "type": "string"},
+ { "name": "becameRequired", "type": "string" },
+ { "name": "addedOptional", "type": "string", "optional": True },
+ ]
+ },
+ {
+ "name": "addedEvent"
+ }
+ ]
+ },
+ {
+ "domain": "addedDomain"
+ }
+ ]
+
+ expected_errors = [
+ "removedDomain: domain has been removed",
+ "Network.removedCommand: command has been removed",
+ "Network.removedEvent: event has been removed",
+ "Network.setExtraHTTPHeaders.mismatched: parameter base type mismatch, 'object' vs 'string'",
+ "Network.setExtraHTTPHeaders.addedRequired: required parameter has been added",
+ "Network.setExtraHTTPHeaders.becameRequired: optional parameter is now required",
+ "Network.setExtraHTTPHeaders.removedRequired: required response parameter has been removed",
+ "Network.setExtraHTTPHeaders.becameOptional: required response parameter is now optional",
+ "Network.requestWillBeSent.removedRequired: required parameter has been removed",
+ "Network.requestWillBeSent.becameOptional: required parameter is now optional",
+ "Network.requestWillBeSent.request parameter->Network.Request.removedField: required property has been removed",
+ "Network.requestWillBeSent.request parameter->Network.Request.becameOptionalField: required property is now optional",
+ ]
+
+ expected_errors_reverse = [
+ "addedDomain: domain has been added",
+ "Network.addedEvent: event has been added",
+ "Network.addedCommand: command has been added",
+ "Network.setExtraHTTPHeaders.mismatched: parameter base type mismatch, 'string' vs 'object'",
+ "Network.setExtraHTTPHeaders.removedRequired: required parameter has been removed",
+ "Network.setExtraHTTPHeaders.becameOptional: required parameter is now optional",
+ "Network.setExtraHTTPHeaders.addedRequired: required response parameter has been added",
+ "Network.setExtraHTTPHeaders.becameRequired: optional response parameter is now required",
+ "Network.requestWillBeSent.becameRequired: optional parameter is now required",
+ "Network.requestWillBeSent.addedRequired: required parameter has been added",
+ ]
+
+ def is_subset(subset, superset, message):
+ for i in range(len(subset)):
+ if subset[i] not in superset:
+ sys.stderr.write("%s error: %s\n" % (message, subset[i]))
+ return False
+ return True
+
+ def errors_match(expected, actual):
+ return (is_subset(actual, expected, "Unexpected") and
+ is_subset(expected, actual, "Missing"))
+
+ return (errors_match(expected_errors,
+ compare_schemas(create_test_schema_1(), create_test_schema_2(), False)) and
+ errors_match(expected_errors_reverse,
+ compare_schemas(create_test_schema_2(), create_test_schema_1(), True)))
+
+
+def main():
+ if not self_test():
+ sys.stderr.write("Self-test failed")
+ return 1
+
+ if len(sys.argv) < 4 or sys.argv[1] != "-o":
+ sys.stderr.write("Usage: %s -o OUTPUT_FILE INPUT_FILE [--show-changes]\n" % sys.argv[0])
+ return 1
+
+ output_path = sys.argv[2]
+ output_file = open(output_path, "w")
+
+ input_path = sys.argv[3]
+ dir_name = os.path.dirname(input_path)
+ schema = load_json(input_path)
+
+ major = schema["version"]["major"]
+ minor = schema["version"]["minor"]
+ version = "%s.%s" % (major, minor)
+ if len(dir_name) == 0:
+ dir_name = "."
+ baseline_path = os.path.normpath(dir_name + "/Inspector-" + version + ".json")
+ baseline_schema = load_json(baseline_path)
+
+ expected_errors = [
+ "Debugger.globalObjectCleared: event has been removed"
+ ]
+
+ errors = compare_schemas(baseline_schema["domains"], schema["domains"], False)
+ unexpected_errors = []
+ for i in range(len(errors)):
+ if errors[i] not in expected_errors:
+ unexpected_errors.append(errors[i])
+ if len(unexpected_errors) > 0:
+ sys.stderr.write(" Compatibility with %s: FAILED\n" % version)
+ for error in unexpected_errors:
+ sys.stderr.write( " %s\n" % error)
+ return 1
+
+ if len(sys.argv) > 4 and sys.argv[4] == "--show-changes":
+ changes = compare_schemas(
+ load_json(input_path)["domains"], load_json(baseline_path)["domains"], True)
+ if len(changes) > 0:
+ print " Public changes since %s:" % version
+ for change in changes:
+ print " %s" % change
+
+ output_file.write("""
+#ifndef InspectorProtocolVersion_h
+#define InspectorProtocolVersion_h
+
+#include "platform/inspector_protocol/String16.h"
+
+namespace blink {
+
+String inspectorProtocolVersion() { return "%s"; }
+
+int inspectorProtocolVersionMajor() { return %s; }
+
+int inspectorProtocolVersionMinor() { return %s; }
+
+}
+
+#endif // !defined(InspectorProtocolVersion_h)
+""" % (version, major, minor))
+
+ output_file.close()
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/deps/v8_inspector/platform/inspector_protocol/protocol.gyp b/deps/v8_inspector/platform/inspector_protocol/protocol.gyp
new file mode 100644
index 0000000000..e30f531e7e
--- /dev/null
+++ b/deps/v8_inspector/platform/inspector_protocol/protocol.gyp
@@ -0,0 +1,89 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'blink_platform_output_dir': '<(SHARED_INTERMEDIATE_DIR)/blink/platform',
+ 'jinja_module_files': [
+ # jinja2/__init__.py contains version string, so sufficient for package
+ '../../deps/jinja2/jinja2/__init__.py',
+ '../../deps/markupsafe/markupsafe/__init__.py', # jinja2 dep
+ ],
+ },
+
+ 'targets': [
+ {
+ # GN version: //third_party/WebKit/Source/platform/inspector_protocol_sources
+ 'target_name': 'protocol_sources',
+ 'type': 'none',
+ 'dependencies': [
+ 'protocol_version'
+ ],
+ 'actions': [
+ {
+ 'action_name': 'generateInspectorProtocolBackendSources',
+ 'inputs': [
+ '<@(jinja_module_files)',
+ # The python script in action below.
+ 'CodeGenerator.py',
+ # Input files for the script.
+ '../../devtools/protocol.json',
+ 'Backend_h.template',
+ 'Dispatcher_h.template',
+ 'Dispatcher_cpp.template',
+ 'Frontend_h.template',
+ 'Frontend_cpp.template',
+ 'TypeBuilder_h.template',
+ 'TypeBuilder_cpp.template',
+ ],
+ 'outputs': [
+ '<(blink_platform_output_dir)/inspector_protocol/Backend.h',
+ '<(blink_platform_output_dir)/inspector_protocol/Dispatcher.cpp',
+ '<(blink_platform_output_dir)/inspector_protocol/Dispatcher.h',
+ '<(blink_platform_output_dir)/inspector_protocol/Frontend.cpp',
+ '<(blink_platform_output_dir)/inspector_protocol/Frontend.h',
+ '<(blink_platform_output_dir)/inspector_protocol/TypeBuilder.cpp',
+ '<(blink_platform_output_dir)/inspector_protocol/TypeBuilder.h',
+ ],
+ 'action': [
+ 'python',
+ 'CodeGenerator.py',
+ '../../devtools/protocol.json',
+ '--output_dir', '<(blink_platform_output_dir)/inspector_protocol',
+ ],
+ 'message': 'Generating Inspector protocol backend sources from protocol.json',
+ },
+ ]
+ },
+ {
+ # GN version: //third_party/WebKit/Source/platform/inspector_protocol_version
+ 'target_name': 'protocol_version',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'action_name': 'generateInspectorProtocolVersion',
+ 'inputs': [
+ 'generate-inspector-protocol-version',
+ '../../devtools/protocol.json',
+ ],
+ 'outputs': [
+ '<(blink_platform_output_dir)/inspector_protocol/InspectorProtocolVersion.h',
+ ],
+ 'variables': {
+ 'generator_include_dirs': [
+ ],
+ },
+ 'action': [
+ 'python',
+ 'generate-inspector-protocol-version',
+ '-o',
+ '<@(_outputs)',
+ '<@(_inputs)'
+ ],
+ 'message': 'Validate inspector protocol for backwards compatibility and generate version file',
+ }
+ ]
+ },
+ ], # targets
+}
diff --git a/deps/v8_inspector/platform/v8_inspector/Atomics.h b/deps/v8_inspector/platform/v8_inspector/Atomics.h
new file mode 100644
index 0000000000..8076f19588
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/Atomics.h
@@ -0,0 +1,27 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef Atomics_h
+#define Atomics_h
+
+#include <stdint.h>
+
+#if COMPILER(MSVC)
+#include <windows.h>
+#endif
+
+namespace blink {
+
+#if COMPILER(MSVC)
+inline int atomicIncrement(int volatile* addend) { return InterlockedIncrement(reinterpret_cast<long volatile*>(addend)); }
+#else
+
+inline int atomicAdd(int volatile* addend, int increment) { return __sync_add_and_fetch(addend, increment); }
+inline int atomicIncrement(int volatile* addend) { return atomicAdd(addend, 1); }
+
+#endif
+
+} // namespace blink
+
+#endif /* Atomics_h */
diff --git a/deps/v8_inspector/platform/v8_inspector/DebuggerScript.js b/deps/v8_inspector/platform/v8_inspector/DebuggerScript.js
new file mode 100644
index 0000000000..85d214e06e
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/DebuggerScript.js
@@ -0,0 +1,705 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+"use strict";
+
+(function () {
+
+var DebuggerScript = {};
+
+/** @enum */
+DebuggerScript.PauseOnExceptionsState = {
+ DontPauseOnExceptions: 0,
+ PauseOnAllExceptions: 1,
+ PauseOnUncaughtExceptions: 2
+};
+
+DebuggerScript._pauseOnExceptionsState = DebuggerScript.PauseOnExceptionsState.DontPauseOnExceptions;
+Debug.clearBreakOnException();
+Debug.clearBreakOnUncaughtException();
+
+/**
+ * @param {!CompileEvent} eventData
+ */
+DebuggerScript.getAfterCompileScript = function(eventData)
+{
+ return DebuggerScript._formatScript(eventData.script().value());
+}
+
+/** @type {!Map<!ScopeType, string>} */
+DebuggerScript._scopeTypeNames = new Map();
+DebuggerScript._scopeTypeNames.set(ScopeType.Global, "global");
+DebuggerScript._scopeTypeNames.set(ScopeType.Local, "local");
+DebuggerScript._scopeTypeNames.set(ScopeType.With, "with");
+DebuggerScript._scopeTypeNames.set(ScopeType.Closure, "closure");
+DebuggerScript._scopeTypeNames.set(ScopeType.Catch, "catch");
+DebuggerScript._scopeTypeNames.set(ScopeType.Block, "block");
+DebuggerScript._scopeTypeNames.set(ScopeType.Script, "script");
+
+/**
+ * @param {function()} fun
+ * @return {?Array<!Scope>}
+ */
+DebuggerScript.getFunctionScopes = function(fun)
+{
+ var mirror = MakeMirror(fun);
+ if (!mirror.isFunction())
+ return null;
+ var functionMirror = /** @type {!FunctionMirror} */(mirror);
+ var count = functionMirror.scopeCount();
+ if (count == 0)
+ return null;
+ var result = [];
+ for (var i = 0; i < count; i++) {
+ var scopeDetails = functionMirror.scope(i).details();
+ var scopeObject = DebuggerScript._buildScopeObject(scopeDetails.type(), scopeDetails.object());
+ if (!scopeObject)
+ continue;
+ result.push({
+ type: /** @type {string} */(DebuggerScript._scopeTypeNames.get(scopeDetails.type())),
+ object: scopeObject,
+ name: scopeDetails.name() || ""
+ });
+ }
+ return result;
+}
+
+/**
+ * @param {Object} object
+ * @return {?GeneratorObjectDetails}
+ */
+DebuggerScript.getGeneratorObjectDetails = function(object)
+{
+ var mirror = MakeMirror(object, true /* transient */);
+ if (!mirror.isGenerator())
+ return null;
+ var generatorMirror = /** @type {!GeneratorMirror} */(mirror);
+ var funcMirror = generatorMirror.func();
+ if (!funcMirror.resolved())
+ return null;
+ var result = {
+ "function": funcMirror.value(),
+ "functionName": funcMirror.debugName(),
+ "status": generatorMirror.status()
+ };
+ var script = funcMirror.script();
+ var location = generatorMirror.sourceLocation() || funcMirror.sourceLocation();
+ if (script && location) {
+ result["location"] = {
+ "scriptId": String(script.id()),
+ "lineNumber": location.line,
+ "columnNumber": location.column
+ };
+ }
+ return result;
+}
+
+/**
+ * @param {Object} object
+ * @return {!Array<!{value: *}>|undefined}
+ */
+DebuggerScript.getCollectionEntries = function(object)
+{
+ var mirror = MakeMirror(object, true /* transient */);
+ if (mirror.isMap())
+ return /** @type {!MapMirror} */(mirror).entries();
+ if (mirror.isSet() || mirror.isIterator()) {
+ var result = [];
+ var values = mirror.isSet() ? /** @type {!SetMirror} */(mirror).values() : /** @type {!IteratorMirror} */(mirror).preview();
+ for (var i = 0; i < values.length; ++i)
+ result.push({ value: values[i] });
+ return result;
+ }
+}
+
+/**
+ * @param {string|undefined} contextData
+ * @return {number}
+ */
+DebuggerScript._executionContextId = function(contextData)
+{
+ if (!contextData)
+ return 0;
+ var firstComma = contextData.indexOf(",");
+ if (firstComma === -1)
+ return 0;
+ var secondComma = contextData.indexOf(",", firstComma + 1);
+ if (secondComma === -1)
+ return 0;
+
+ return parseInt(contextData.substring(firstComma + 1, secondComma), 10) || 0;
+}
+
+/**
+ * @param {string} contextGroupId
+ * @return {!Array<!FormattedScript>}
+ */
+DebuggerScript.getScripts = function(contextGroupId)
+{
+ var result = [];
+ var scripts = Debug.scripts();
+ var contextDataPrefix = null;
+ if (contextGroupId)
+ contextDataPrefix = contextGroupId + ",";
+ for (var i = 0; i < scripts.length; ++i) {
+ var script = scripts[i];
+ if (contextDataPrefix) {
+ if (!script.context_data)
+ continue;
+ // Context data is a string in the following format:
+ // <contextGroupId>,<contextId>,("default"|"nondefault")
+ if (script.context_data.indexOf(contextDataPrefix) !== 0)
+ continue;
+ }
+ result.push(DebuggerScript._formatScript(script));
+ }
+ return result;
+}
+
+/**
+ * @param {!Script} script
+ * @return {!FormattedScript}
+ */
+DebuggerScript._formatScript = function(script)
+{
+ var lineEnds = script.line_ends;
+ var lineCount = lineEnds.length;
+ var endLine = script.line_offset + lineCount - 1;
+ var endColumn;
+ // V8 will not count last line if script source ends with \n.
+ if (script.source[script.source.length - 1] === '\n') {
+ endLine += 1;
+ endColumn = 0;
+ } else {
+ if (lineCount === 1)
+ endColumn = script.source.length + script.column_offset;
+ else
+ endColumn = script.source.length - (lineEnds[lineCount - 2] + 1);
+ }
+ return {
+ id: script.id,
+ name: script.nameOrSourceURL(),
+ sourceURL: script.source_url,
+ sourceMappingURL: script.source_mapping_url,
+ source: script.source,
+ startLine: script.line_offset,
+ startColumn: script.column_offset,
+ endLine: endLine,
+ endColumn: endColumn,
+ executionContextId: DebuggerScript._executionContextId(script.context_data),
+ isContentScript: !!script.context_data && script.context_data.endsWith(",nondefault"),
+ isInternalScript: script.is_debugger_script
+ };
+}
+
+/**
+ * @param {!ExecutionState} execState
+ * @param {!BreakpointInfo} info
+ * @return {string|undefined}
+ */
+DebuggerScript.setBreakpoint = function(execState, info)
+{
+ var positionAlignment = info.interstatementLocation ? Debug.BreakPositionAlignment.BreakPosition : Debug.BreakPositionAlignment.Statement;
+ var breakId = Debug.setScriptBreakPointById(info.sourceID, info.lineNumber, info.columnNumber, info.condition, undefined, positionAlignment);
+
+ var locations = Debug.findBreakPointActualLocations(breakId);
+ if (!locations.length)
+ return undefined;
+ info.lineNumber = locations[0].line;
+ info.columnNumber = locations[0].column;
+ return breakId.toString();
+}
+
+/**
+ * @param {!ExecutionState} execState
+ * @param {!{breakpointId: number}} info
+ */
+DebuggerScript.removeBreakpoint = function(execState, info)
+{
+ Debug.findBreakPoint(info.breakpointId, true);
+}
+
+/**
+ * @return {number}
+ */
+DebuggerScript.pauseOnExceptionsState = function()
+{
+ return DebuggerScript._pauseOnExceptionsState;
+}
+
+/**
+ * @param {number} newState
+ */
+DebuggerScript.setPauseOnExceptionsState = function(newState)
+{
+ DebuggerScript._pauseOnExceptionsState = newState;
+
+ if (DebuggerScript.PauseOnExceptionsState.PauseOnAllExceptions === newState)
+ Debug.setBreakOnException();
+ else
+ Debug.clearBreakOnException();
+
+ if (DebuggerScript.PauseOnExceptionsState.PauseOnUncaughtExceptions === newState)
+ Debug.setBreakOnUncaughtException();
+ else
+ Debug.clearBreakOnUncaughtException();
+}
+
+/**
+ * @param {!ExecutionState} execState
+ * @param {number} limit
+ * @return {!Array<!JavaScriptCallFrame>}
+ */
+DebuggerScript.currentCallFrames = function(execState, limit)
+{
+ var frames = [];
+ for (var i = 0; i < execState.frameCount() && (!limit || i < limit); ++i)
+ frames.push(DebuggerScript._frameMirrorToJSCallFrame(execState.frame(i)));
+ return frames;
+}
+
+/**
+ * @param {!ExecutionState} execState
+ */
+DebuggerScript.stepIntoStatement = function(execState)
+{
+ execState.prepareStep(Debug.StepAction.StepIn);
+}
+
+/**
+ * @param {!ExecutionState} execState
+ */
+DebuggerScript.stepFrameStatement = function(execState)
+{
+ execState.prepareStep(Debug.StepAction.StepFrame);
+}
+
+/**
+ * @param {!ExecutionState} execState
+ */
+DebuggerScript.stepOverStatement = function(execState)
+{
+ execState.prepareStep(Debug.StepAction.StepNext);
+}
+
+/**
+ * @param {!ExecutionState} execState
+ */
+DebuggerScript.stepOutOfFunction = function(execState)
+{
+ execState.prepareStep(Debug.StepAction.StepOut);
+}
+
+DebuggerScript.clearStepping = function()
+{
+ Debug.clearStepping();
+}
+
+// Returns array in form:
+// [ 0, <v8_result_report> ] in case of success
+// or [ 1, <general_error_message>, <compiler_message>, <line_number>, <column_number> ] in case of compile error, numbers are 1-based.
+// or throws exception with message.
+/**
+ * @param {number} scriptId
+ * @param {string} newSource
+ * @param {boolean} preview
+ * @return {!Array<*>}
+ */
+DebuggerScript.liveEditScriptSource = function(scriptId, newSource, preview)
+{
+ var scripts = Debug.scripts();
+ var scriptToEdit = null;
+ for (var i = 0; i < scripts.length; i++) {
+ if (scripts[i].id == scriptId) {
+ scriptToEdit = scripts[i];
+ break;
+ }
+ }
+ if (!scriptToEdit)
+ throw("Script not found");
+
+ var changeLog = [];
+ try {
+ var result = Debug.LiveEdit.SetScriptSource(scriptToEdit, newSource, preview, changeLog);
+ return [0, result.stack_modified];
+ } catch (e) {
+ if (e instanceof Debug.LiveEdit.Failure && "details" in e) {
+ var details = /** @type {!LiveEditErrorDetails} */(e.details);
+ if (details.type === "liveedit_compile_error") {
+ var startPosition = details.position.start;
+ return [1, String(e), String(details.syntaxErrorMessage), Number(startPosition.line), Number(startPosition.column)];
+ }
+ }
+ throw e;
+ }
+}
+
+/**
+ * @param {!ExecutionState} execState
+ */
+DebuggerScript.clearBreakpoints = function(execState)
+{
+ Debug.clearAllBreakPoints();
+}
+
+/**
+ * @param {!ExecutionState} execState
+ * @param {!{enabled: boolean}} info
+ */
+DebuggerScript.setBreakpointsActivated = function(execState, info)
+{
+ Debug.debuggerFlags().breakPointsActive.setValue(info.enabled);
+}
+
+/**
+ * @param {!BreakEvent} eventData
+ */
+DebuggerScript.getBreakpointNumbers = function(eventData)
+{
+ var breakpoints = eventData.breakPointsHit();
+ var numbers = [];
+ if (!breakpoints)
+ return numbers;
+
+ for (var i = 0; i < breakpoints.length; i++) {
+ var breakpoint = breakpoints[i];
+ var scriptBreakPoint = breakpoint.script_break_point();
+ numbers.push(scriptBreakPoint ? scriptBreakPoint.number() : breakpoint.number());
+ }
+ return numbers;
+}
+
+// NOTE: This function is performance critical, as it can be run on every
+// statement that generates an async event (like addEventListener) to support
+// asynchronous call stacks. Thus, when possible, initialize the data lazily.
+/**
+ * @param {!FrameMirror} frameMirror
+ * @return {!JavaScriptCallFrame}
+ */
+DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror)
+{
+ // Stuff that can not be initialized lazily (i.e. valid while paused with a valid break_id).
+ // The frameMirror and scopeMirror can be accessed only while paused on the debugger.
+ var frameDetails = frameMirror.details();
+
+ var funcObject = frameDetails.func();
+ var sourcePosition = frameDetails.sourcePosition();
+ var thisObject = frameDetails.receiver();
+
+ var isAtReturn = !!frameDetails.isAtReturn();
+ var returnValue = isAtReturn ? frameDetails.returnValue() : undefined;
+
+ var scopeMirrors = frameMirror.allScopes(false);
+ /** @type {!Array<ScopeType>} */
+ var scopeTypes = new Array(scopeMirrors.length);
+ /** @type {?Array<!Object>} */
+ var scopeObjects = new Array(scopeMirrors.length);
+ /** @type {!Array<string|undefined>} */
+ var scopeNames = new Array(scopeMirrors.length);
+ /** @type {?Array<number>} */
+ var scopeStartPositions = new Array(scopeMirrors.length);
+ /** @type {?Array<number>} */
+ var scopeEndPositions = new Array(scopeMirrors.length);
+ /** @type {?Array<function()|null>} */
+ var scopeFunctions = new Array(scopeMirrors.length);
+ for (var i = 0; i < scopeMirrors.length; ++i) {
+ var scopeDetails = scopeMirrors[i].details();
+ scopeTypes[i] = scopeDetails.type();
+ scopeObjects[i] = scopeDetails.object();
+ scopeNames[i] = scopeDetails.name();
+ scopeStartPositions[i] = scopeDetails.startPosition ? scopeDetails.startPosition() : 0;
+ scopeEndPositions[i] = scopeDetails.endPosition ? scopeDetails.endPosition() : 0;
+ scopeFunctions[i] = scopeDetails.func ? scopeDetails.func() : null;
+ }
+
+ // Calculated lazily.
+ var scopeChain;
+ var funcMirror;
+ var location;
+ /** @type {!Array<?RawLocation>} */
+ var scopeStartLocations;
+ /** @type {!Array<?RawLocation>} */
+ var scopeEndLocations;
+ var details;
+
+ /**
+ * @param {!ScriptMirror|undefined} script
+ * @param {number} pos
+ * @return {?RawLocation}
+ */
+ function createLocation(script, pos)
+ {
+ if (!script)
+ return null;
+
+ var location = script.locationFromPosition(pos, true);
+ return {
+ "lineNumber": location.line,
+ "columnNumber": location.column,
+ "scriptId": String(script.id())
+ }
+ }
+
+ /**
+ * @return {!Array<!Object>}
+ */
+ function ensureScopeChain()
+ {
+ if (!scopeChain) {
+ scopeChain = [];
+ scopeStartLocations = [];
+ scopeEndLocations = [];
+ for (var i = 0, j = 0; i < scopeObjects.length; ++i) {
+ var scopeObject = DebuggerScript._buildScopeObject(scopeTypes[i], scopeObjects[i]);
+ if (scopeObject) {
+ scopeTypes[j] = scopeTypes[i];
+ scopeNames[j] = scopeNames[i];
+ scopeChain[j] = scopeObject;
+
+ var funcMirror = scopeFunctions ? MakeMirror(scopeFunctions[i]) : null;
+ if (!funcMirror || !funcMirror.isFunction())
+ funcMirror = new UnresolvedFunctionMirror(funcObject);
+
+ var script = /** @type {!FunctionMirror} */(funcMirror).script();
+ scopeStartLocations[j] = createLocation(script, scopeStartPositions[i]);
+ scopeEndLocations[j] = createLocation(script, scopeEndPositions[i]);
+ ++j;
+ }
+ }
+ scopeTypes.length = scopeChain.length;
+ scopeNames.length = scopeChain.length;
+ scopeObjects = null; // Free for GC.
+ scopeFunctions = null;
+ scopeStartPositions = null;
+ scopeEndPositions = null;
+ }
+ return scopeChain;
+ }
+
+ /**
+ * @return {!JavaScriptCallFrameDetails}
+ */
+ function lazyDetails()
+ {
+ if (!details) {
+ var scopeObjects = ensureScopeChain();
+ var script = ensureFuncMirror().script();
+ /** @type {!Array<Scope>} */
+ var scopes = [];
+ for (var i = 0; i < scopeObjects.length; ++i) {
+ var scope = {
+ "type": /** @type {string} */(DebuggerScript._scopeTypeNames.get(scopeTypes[i])),
+ "object": scopeObjects[i],
+ };
+ if (scopeNames[i])
+ scope.name = scopeNames[i];
+ if (scopeStartLocations[i])
+ scope.startLocation = /** @type {!RawLocation} */(scopeStartLocations[i]);
+ if (scopeEndLocations[i])
+ scope.endLocation = /** @type {!RawLocation} */(scopeEndLocations[i]);
+ scopes.push(scope);
+ }
+ details = {
+ "functionName": ensureFuncMirror().debugName(),
+ "location": {
+ "lineNumber": line(),
+ "columnNumber": column(),
+ "scriptId": String(script.id())
+ },
+ "this": thisObject,
+ "scopeChain": scopes
+ };
+ var functionLocation = ensureFuncMirror().sourceLocation();
+ if (functionLocation) {
+ details.functionLocation = {
+ "lineNumber": functionLocation.line,
+ "columnNumber": functionLocation.column,
+ "scriptId": String(script.id())
+ };
+ }
+ if (isAtReturn)
+ details.returnValue = returnValue;
+ }
+ return details;
+ }
+
+ /**
+ * @return {!FunctionMirror}
+ */
+ function ensureFuncMirror()
+ {
+ if (!funcMirror) {
+ funcMirror = MakeMirror(funcObject);
+ if (!funcMirror.isFunction())
+ funcMirror = new UnresolvedFunctionMirror(funcObject);
+ }
+ return /** @type {!FunctionMirror} */(funcMirror);
+ }
+
+ /**
+ * @return {!{line: number, column: number}}
+ */
+ function ensureLocation()
+ {
+ if (!location) {
+ var script = ensureFuncMirror().script();
+ if (script)
+ location = script.locationFromPosition(sourcePosition, true);
+ if (!location)
+ location = { line: 0, column: 0 };
+ }
+ return location;
+ }
+
+ /**
+ * @return {number}
+ */
+ function line()
+ {
+ return ensureLocation().line;
+ }
+
+ /**
+ * @return {number}
+ */
+ function column()
+ {
+ return ensureLocation().column;
+ }
+
+ /**
+ * @return {number}
+ */
+ function contextId()
+ {
+ var mirror = ensureFuncMirror();
+ // Old V8 do not have context() function on these objects
+ if (!mirror.context)
+ return DebuggerScript._executionContextId(mirror.script().value().context_data);
+ var context = mirror.context();
+ if (context)
+ return DebuggerScript._executionContextId(context.data());
+ return 0;
+ }
+
+ /**
+ * @return {number|undefined}
+ */
+ function sourceID()
+ {
+ var script = ensureFuncMirror().script();
+ return script && script.id();
+ }
+
+ /**
+ * @param {string} expression
+ * @return {*}
+ */
+ function evaluate(expression)
+ {
+ return frameMirror.evaluate(expression, false).value();
+ }
+
+ /** @return {undefined} */
+ function restart()
+ {
+ return frameMirror.restart();
+ }
+
+ /**
+ * @param {number} scopeNumber
+ * @param {string} variableName
+ * @param {*} newValue
+ */
+ function setVariableValue(scopeNumber, variableName, newValue)
+ {
+ var scopeMirror = frameMirror.scope(scopeNumber);
+ if (!scopeMirror)
+ throw new Error("Incorrect scope index");
+ scopeMirror.setVariableValue(variableName, newValue);
+ }
+
+ return {
+ "sourceID": sourceID,
+ "line": line,
+ "column": column,
+ "contextId": contextId,
+ "thisObject": thisObject,
+ "evaluate": evaluate,
+ "restart": restart,
+ "setVariableValue": setVariableValue,
+ "isAtReturn": isAtReturn,
+ "details": lazyDetails
+ };
+}
+
+/**
+ * @param {number} scopeType
+ * @param {!Object} scopeObject
+ * @return {!Object|undefined}
+ */
+DebuggerScript._buildScopeObject = function(scopeType, scopeObject)
+{
+ var result;
+ switch (scopeType) {
+ case ScopeType.Local:
+ case ScopeType.Closure:
+ case ScopeType.Catch:
+ case ScopeType.Block:
+ case ScopeType.Script:
+ // For transient objects we create a "persistent" copy that contains
+ // the same properties.
+ // Reset scope object prototype to null so that the proto properties
+ // don't appear in the local scope section.
+ var properties = /** @type {!ObjectMirror} */(MakeMirror(scopeObject, true /* transient */)).properties();
+ // Almost always Script scope will be empty, so just filter out that noise.
+ // Also drop empty Block scopes, should we get any.
+ if (!properties.length && (scopeType === ScopeType.Script || scopeType === ScopeType.Block))
+ break;
+ result = { __proto__: null };
+ for (var j = 0; j < properties.length; j++) {
+ var name = properties[j].name();
+ if (name.length === 0 || name.charAt(0) === ".")
+ continue; // Skip internal variables like ".arguments" and variables with empty name
+ result[name] = properties[j].value_;
+ }
+ break;
+ case ScopeType.Global:
+ case ScopeType.With:
+ result = scopeObject;
+ break;
+ }
+ return result;
+}
+
+// We never resolve Mirror by its handle so to avoid memory leaks caused by Mirrors in the cache we disable it.
+ToggleMirrorCache(false);
+
+return DebuggerScript;
+})();
diff --git a/deps/v8_inspector/platform/v8_inspector/InjectedScript.cpp b/deps/v8_inspector/platform/v8_inspector/InjectedScript.cpp
new file mode 100644
index 0000000000..65ed3bdce9
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/InjectedScript.cpp
@@ -0,0 +1,538 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "platform/v8_inspector/InjectedScript.h"
+
+#include "platform/inspector_protocol/Parser.h"
+#include "platform/inspector_protocol/String16.h"
+#include "platform/inspector_protocol/Values.h"
+#include "platform/v8_inspector/InjectedScriptNative.h"
+#include "platform/v8_inspector/InjectedScriptSource.h"
+#include "platform/v8_inspector/InspectedContext.h"
+#include "platform/v8_inspector/RemoteObjectId.h"
+#include "platform/v8_inspector/V8Compat.h"
+#include "platform/v8_inspector/V8Console.h"
+#include "platform/v8_inspector/V8DebuggerImpl.h"
+#include "platform/v8_inspector/V8FunctionCall.h"
+#include "platform/v8_inspector/V8InjectedScriptHost.h"
+#include "platform/v8_inspector/V8InspectorSessionImpl.h"
+#include "platform/v8_inspector/V8StackTraceImpl.h"
+#include "platform/v8_inspector/V8StringUtil.h"
+#include "platform/v8_inspector/public/V8Debugger.h"
+#include "platform/v8_inspector/public/V8DebuggerClient.h"
+#include "platform/v8_inspector/public/V8ToProtocolValue.h"
+
+using blink::protocol::Array;
+using blink::protocol::Debugger::CallFrame;
+using blink::protocol::Debugger::CollectionEntry;
+using blink::protocol::Debugger::FunctionDetails;
+using blink::protocol::Debugger::GeneratorObjectDetails;
+using blink::protocol::Runtime::PropertyDescriptor;
+using blink::protocol::Runtime::InternalPropertyDescriptor;
+using blink::protocol::Runtime::RemoteObject;
+using blink::protocol::Maybe;
+
+namespace blink {
+
+static bool hasInternalError(ErrorString* errorString, bool hasError)
+{
+ if (hasError)
+ *errorString = "Internal error";
+ return hasError;
+}
+
+std::unique_ptr<InjectedScript> InjectedScript::create(InspectedContext* inspectedContext)
+{
+ v8::Isolate* isolate = inspectedContext->isolate();
+ v8::HandleScope handles(isolate);
+ v8::Local<v8::Context> context = inspectedContext->context();
+ v8::Context::Scope scope(context);
+
+ std::unique_ptr<InjectedScriptNative> injectedScriptNative(new InjectedScriptNative(isolate));
+ v8::Local<v8::Object> scriptHostWrapper = V8InjectedScriptHost::create(context, inspectedContext->debugger());
+ injectedScriptNative->setOnInjectedScriptHost(scriptHostWrapper);
+
+ // Inject javascript into the context. The compiled script is supposed to evaluate into
+ // a single anonymous function(it's anonymous to avoid cluttering the global object with
+ // inspector's stuff) the function is called a few lines below with InjectedScriptHost wrapper,
+ // injected script id and explicit reference to the inspected global object. The function is expected
+ // to create and configure InjectedScript instance that is going to be used by the inspector.
+ String16 injectedScriptSource(reinterpret_cast<const char*>(InjectedScriptSource_js), sizeof(InjectedScriptSource_js));
+ v8::Local<v8::Value> value;
+ if (!inspectedContext->debugger()->compileAndRunInternalScript(context, toV8String(isolate, injectedScriptSource)).ToLocal(&value))
+ return nullptr;
+ DCHECK(value->IsFunction());
+ v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(value);
+ v8::Local<v8::Object> windowGlobal = context->Global();
+ v8::Local<v8::Value> info[] = { scriptHostWrapper, windowGlobal, v8::Number::New(isolate, inspectedContext->contextId()) };
+ v8::MicrotasksScope microtasksScope(isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
+ v8::Local<v8::Value> injectedScriptValue;
+ if (!function->Call(context, windowGlobal, PROTOCOL_ARRAY_LENGTH(info), info).ToLocal(&injectedScriptValue))
+ return nullptr;
+ if (!injectedScriptValue->IsObject())
+ return nullptr;
+ return wrapUnique(new InjectedScript(inspectedContext, injectedScriptValue.As<v8::Object>(), std::move(injectedScriptNative)));
+}
+
+InjectedScript::InjectedScript(InspectedContext* context, v8::Local<v8::Object> object, std::unique_ptr<InjectedScriptNative> injectedScriptNative)
+ : m_context(context)
+ , m_value(context->isolate(), object)
+ , m_native(std::move(injectedScriptNative))
+{
+}
+
+InjectedScript::~InjectedScript()
+{
+}
+
+void InjectedScript::getProperties(ErrorString* errorString, v8::Local<v8::Object> object, const String16& groupName, bool ownProperties, bool accessorPropertiesOnly, bool generatePreview, std::unique_ptr<Array<PropertyDescriptor>>* properties, Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails)
+{
+ v8::HandleScope handles(m_context->isolate());
+ V8FunctionCall function(m_context->debugger(), m_context->context(), v8Value(), "getProperties");
+ function.appendArgument(object);
+ function.appendArgument(groupName);
+ function.appendArgument(ownProperties);
+ function.appendArgument(accessorPropertiesOnly);
+ function.appendArgument(generatePreview);
+
+ v8::TryCatch tryCatch(m_context->isolate());
+ v8::Local<v8::Value> resultValue = function.callWithoutExceptionHandling();
+ if (tryCatch.HasCaught()) {
+ *exceptionDetails = createExceptionDetails(tryCatch.Message());
+ // FIXME: make properties optional
+ *properties = Array<PropertyDescriptor>::create();
+ return;
+ }
+
+ std::unique_ptr<protocol::Value> protocolValue = toProtocolValue(function.context(), resultValue);
+ if (hasInternalError(errorString, !protocolValue))
+ return;
+ protocol::ErrorSupport errors(errorString);
+ std::unique_ptr<Array<PropertyDescriptor>> result = Array<PropertyDescriptor>::parse(protocolValue.get(), &errors);
+ if (!hasInternalError(errorString, errors.hasErrors()))
+ *properties = std::move(result);
+}
+
+void InjectedScript::releaseObject(const String16& objectId)
+{
+ std::unique_ptr<protocol::Value> parsedObjectId = protocol::parseJSON(objectId);
+ if (!parsedObjectId)
+ return;
+ protocol::DictionaryValue* object = protocol::DictionaryValue::cast(parsedObjectId.get());
+ if (!object)
+ return;
+ int boundId = 0;
+ if (!object->getNumber("id", &boundId))
+ return;
+ m_native->unbind(boundId);
+}
+
+std::unique_ptr<protocol::Runtime::RemoteObject> InjectedScript::wrapObject(ErrorString* errorString, v8::Local<v8::Value> value, const String16& groupName, bool forceValueType, bool generatePreview) const
+{
+ v8::HandleScope handles(m_context->isolate());
+ v8::Local<v8::Value> wrappedObject;
+ if (!wrapValue(errorString, value, groupName, forceValueType, generatePreview).ToLocal(&wrappedObject))
+ return nullptr;
+ protocol::ErrorSupport errors;
+ std::unique_ptr<protocol::Runtime::RemoteObject> remoteObject = protocol::Runtime::RemoteObject::parse(toProtocolValue(m_context->context(), wrappedObject).get(), &errors);
+ if (!remoteObject)
+ *errorString = "Object has too long reference chain";
+ return remoteObject;
+}
+
+bool InjectedScript::wrapObjectProperty(ErrorString* errorString, v8::Local<v8::Object> object, v8::Local<v8::Value> key, const String16& groupName, bool forceValueType, bool generatePreview) const
+{
+ v8::Local<v8::Value> property;
+ if (hasInternalError(errorString, !object->Get(m_context->context(), key).ToLocal(&property)))
+ return false;
+ v8::Local<v8::Value> wrappedProperty;
+ if (!wrapValue(errorString, property, groupName, forceValueType, generatePreview).ToLocal(&wrappedProperty))
+ return false;
+ v8::Maybe<bool> success = object->Set(m_context->context(), key, wrappedProperty);
+ if (hasInternalError(errorString, success.IsNothing() || !success.FromJust()))
+ return false;
+ return true;
+}
+
+bool InjectedScript::wrapPropertyInArray(ErrorString* errorString, v8::Local<v8::Array> array, v8::Local<v8::String> property, const String16& groupName, bool forceValueType, bool generatePreview) const
+{
+ V8FunctionCall function(m_context->debugger(), m_context->context(), v8Value(), "wrapPropertyInArray");
+ function.appendArgument(array);
+ function.appendArgument(property);
+ function.appendArgument(groupName);
+ function.appendArgument(canAccessInspectedWindow());
+ function.appendArgument(forceValueType);
+ function.appendArgument(generatePreview);
+ bool hadException = false;
+ function.call(hadException);
+ return !hasInternalError(errorString, hadException);
+}
+
+bool InjectedScript::wrapObjectsInArray(ErrorString* errorString, v8::Local<v8::Array> array, const String16& groupName, bool forceValueType, bool generatePreview) const
+{
+ V8FunctionCall function(m_context->debugger(), m_context->context(), v8Value(), "wrapObjectsInArray");
+ function.appendArgument(array);
+ function.appendArgument(groupName);
+ function.appendArgument(canAccessInspectedWindow());
+ function.appendArgument(forceValueType);
+ function.appendArgument(generatePreview);
+ bool hadException = false;
+ function.call(hadException);
+ return !hasInternalError(errorString, hadException);
+}
+
+v8::MaybeLocal<v8::Value> InjectedScript::wrapValue(ErrorString* errorString, v8::Local<v8::Value> value, const String16& groupName, bool forceValueType, bool generatePreview) const
+{
+ V8FunctionCall function(m_context->debugger(), m_context->context(), v8Value(), "wrapObject");
+ function.appendArgument(value);
+ function.appendArgument(groupName);
+ function.appendArgument(canAccessInspectedWindow());
+ function.appendArgument(forceValueType);
+ function.appendArgument(generatePreview);
+ bool hadException = false;
+ v8::Local<v8::Value> r = function.call(hadException);
+ if (hasInternalError(errorString, hadException || r.IsEmpty()))
+ return v8::MaybeLocal<v8::Value>();
+ return r;
+}
+
+std::unique_ptr<protocol::Runtime::RemoteObject> InjectedScript::wrapTable(v8::Local<v8::Value> table, v8::Local<v8::Value> columns) const
+{
+ v8::HandleScope handles(m_context->isolate());
+ V8FunctionCall function(m_context->debugger(), m_context->context(), v8Value(), "wrapTable");
+ function.appendArgument(canAccessInspectedWindow());
+ function.appendArgument(table);
+ if (columns.IsEmpty())
+ function.appendArgument(false);
+ else
+ function.appendArgument(columns);
+ bool hadException = false;
+ v8::Local<v8::Value> r = function.call(hadException);
+ if (hadException)
+ return nullptr;
+ protocol::ErrorSupport errors;
+ return protocol::Runtime::RemoteObject::parse(toProtocolValue(m_context->context(), r).get(), &errors);
+}
+
+bool InjectedScript::findObject(ErrorString* errorString, const RemoteObjectId& objectId, v8::Local<v8::Value>* outObject) const
+{
+ *outObject = m_native->objectForId(objectId.id());
+ if (outObject->IsEmpty())
+ *errorString = "Could not find object with given id";
+ return !outObject->IsEmpty();
+}
+
+String16 InjectedScript::objectGroupName(const RemoteObjectId& objectId) const
+{
+ return m_native->groupName(objectId.id());
+}
+
+void InjectedScript::releaseObjectGroup(const String16& objectGroup)
+{
+ m_native->releaseObjectGroup(objectGroup);
+ if (objectGroup == "console")
+ m_lastEvaluationResult.Reset();
+}
+
+void InjectedScript::setCustomObjectFormatterEnabled(bool enabled)
+{
+ v8::HandleScope handles(m_context->isolate());
+ V8FunctionCall function(m_context->debugger(), m_context->context(), v8Value(), "setCustomObjectFormatterEnabled");
+ function.appendArgument(enabled);
+ bool hadException = false;
+ function.call(hadException);
+ DCHECK(!hadException);
+}
+
+bool InjectedScript::canAccessInspectedWindow() const
+{
+ v8::Local<v8::Context> callingContext = m_context->isolate()->GetCallingContext();
+ if (callingContext.IsEmpty())
+ return true;
+ return m_context->debugger()->client()->callingContextCanAccessContext(callingContext, m_context->context());
+}
+
+v8::Local<v8::Value> InjectedScript::v8Value() const
+{
+ return m_value.Get(m_context->isolate());
+}
+
+v8::Local<v8::Value> InjectedScript::lastEvaluationResult() const
+{
+ if (m_lastEvaluationResult.IsEmpty())
+ return v8::Undefined(m_context->isolate());
+ return m_lastEvaluationResult.Get(m_context->isolate());
+}
+
+v8::MaybeLocal<v8::Value> InjectedScript::resolveCallArgument(ErrorString* errorString, protocol::Runtime::CallArgument* callArgument)
+{
+ if (callArgument->hasObjectId()) {
+ std::unique_ptr<RemoteObjectId> remoteObjectId = RemoteObjectId::parse(errorString, callArgument->getObjectId(""));
+ if (!remoteObjectId)
+ return v8::MaybeLocal<v8::Value>();
+ if (remoteObjectId->contextId() != m_context->contextId()) {
+ *errorString = "Argument should belong to the same JavaScript world as target object";
+ return v8::MaybeLocal<v8::Value>();
+ }
+ v8::Local<v8::Value> object;
+ if (!findObject(errorString, *remoteObjectId, &object))
+ return v8::MaybeLocal<v8::Value>();
+ return object;
+ }
+ if (callArgument->hasValue()) {
+ String16 value = callArgument->getValue(nullptr)->toJSONString();
+ if (callArgument->getType(String16()) == "number")
+ value = "Number(" + value + ")";
+ v8::Local<v8::Value> object;
+ if (!m_context->debugger()->compileAndRunInternalScript(m_context->context(), toV8String(m_context->isolate(), value)).ToLocal(&object)) {
+ *errorString = "Couldn't parse value object in call argument";
+ return v8::MaybeLocal<v8::Value>();
+ }
+ return object;
+ }
+ return v8::Undefined(m_context->isolate());
+}
+
+std::unique_ptr<protocol::Runtime::ExceptionDetails> InjectedScript::createExceptionDetails(v8::Local<v8::Message> message)
+{
+ std::unique_ptr<protocol::Runtime::ExceptionDetails> exceptionDetailsObject = protocol::Runtime::ExceptionDetails::create().setText(toProtocolString(message->Get())).build();
+ exceptionDetailsObject->setUrl(toProtocolStringWithTypeCheck(message->GetScriptResourceName()));
+ exceptionDetailsObject->setScriptId(String16::number(message->GetScriptOrigin().ScriptID()->Value()));
+
+ v8::Maybe<int> lineNumber = message->GetLineNumber(m_context->context());
+ if (lineNumber.IsJust())
+ exceptionDetailsObject->setLine(lineNumber.FromJust());
+ v8::Maybe<int> columnNumber = message->GetStartColumn(m_context->context());
+ if (columnNumber.IsJust())
+ exceptionDetailsObject->setColumn(columnNumber.FromJust());
+
+ v8::Local<v8::StackTrace> stackTrace = message->GetStackTrace();
+ if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0)
+ exceptionDetailsObject->setStack(m_context->debugger()->createStackTrace(stackTrace, stackTrace->GetFrameCount())->buildInspectorObject());
+ return exceptionDetailsObject;
+}
+
+void InjectedScript::wrapEvaluateResult(ErrorString* errorString, v8::MaybeLocal<v8::Value> maybeResultValue, const v8::TryCatch& tryCatch, const String16& objectGroup, bool returnByValue, bool generatePreview, std::unique_ptr<protocol::Runtime::RemoteObject>* result, Maybe<bool>* wasThrown, Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails)
+{
+ v8::Local<v8::Value> resultValue;
+ if (!tryCatch.HasCaught()) {
+ if (hasInternalError(errorString, !maybeResultValue.ToLocal(&resultValue)))
+ return;
+ std::unique_ptr<RemoteObject> remoteObject = wrapObject(errorString, resultValue, objectGroup, returnByValue, generatePreview);
+ if (!remoteObject)
+ return;
+ if (objectGroup == "console")
+ m_lastEvaluationResult.Reset(m_context->isolate(), resultValue);
+ *result = std::move(remoteObject);
+ if (wasThrown)
+ *wasThrown = false;
+ } else {
+ v8::Local<v8::Value> exception = tryCatch.Exception();
+ std::unique_ptr<RemoteObject> remoteObject = wrapObject(errorString, exception, objectGroup, false, generatePreview && !exception->IsNativeError());
+ if (!remoteObject)
+ return;
+ *result = std::move(remoteObject);
+ if (exceptionDetails)
+ *exceptionDetails = createExceptionDetails(tryCatch.Message());
+ if (wasThrown)
+ *wasThrown = true;
+ }
+}
+
+v8::MaybeLocal<v8::Object> InjectedScript::commandLineAPI(ErrorString* errorString)
+{
+ v8::Isolate* isolate = m_context->isolate();
+ if (m_commandLineAPI.IsEmpty()) {
+ V8FunctionCall function(m_context->debugger(), m_context->context(), v8Value(), "installCommandLineAPI");
+ function.appendArgument(V8Console::createCommandLineAPI(m_context));
+ bool hadException = false;
+ v8::Local<v8::Value> extension = function.call(hadException, false);
+ if (hasInternalError(errorString, hadException || extension.IsEmpty() || !extension->IsObject()))
+ return v8::MaybeLocal<v8::Object>();
+ m_commandLineAPI.Reset(isolate, extension.As<v8::Object>());
+ }
+ return m_commandLineAPI.Get(m_context->isolate());
+}
+
+InjectedScript::Scope::Scope(ErrorString* errorString, V8DebuggerImpl* debugger, int contextGroupId)
+ : m_errorString(errorString)
+ , m_debugger(debugger)
+ , m_contextGroupId(contextGroupId)
+ , m_injectedScript(nullptr)
+ , m_handleScope(debugger->isolate())
+ , m_tryCatch(debugger->isolate())
+ , m_ignoreExceptionsAndMuteConsole(false)
+ , m_previousPauseOnExceptionsState(V8DebuggerImpl::DontPauseOnExceptions)
+ , m_userGesture(false)
+{
+}
+
+bool InjectedScript::Scope::initialize()
+{
+ cleanup();
+ // TODO(dgozman): what if we reattach to the same context group during evaluate? Introduce a session id?
+ V8InspectorSessionImpl* session = m_debugger->sessionForContextGroup(m_contextGroupId);
+ if (!session) {
+ *m_errorString = "Internal error";
+ return false;
+ }
+ findInjectedScript(session);
+ if (!m_injectedScript)
+ return false;
+ m_context = m_injectedScript->context()->context();
+ m_context->Enter();
+ return true;
+}
+
+bool InjectedScript::Scope::installCommandLineAPI()
+{
+ DCHECK(m_injectedScript && !m_context.IsEmpty() && m_global.IsEmpty());
+ v8::Local<v8::Object> extensionObject;
+ if (!m_injectedScript->commandLineAPI(m_errorString).ToLocal(&extensionObject))
+ return false;
+ m_extensionPrivate = V8Debugger::scopeExtensionPrivate(m_debugger->isolate());
+ v8::Local<v8::Object> global = m_context->Global();
+ if (!global->SetPrivate(m_context, m_extensionPrivate, extensionObject).FromMaybe(false)) {
+ *m_errorString = "Internal error";
+ return false;
+ }
+ m_global = global;
+ return true;
+}
+
+void InjectedScript::Scope::ignoreExceptionsAndMuteConsole()
+{
+ DCHECK(!m_ignoreExceptionsAndMuteConsole);
+ m_ignoreExceptionsAndMuteConsole = true;
+ m_debugger->client()->muteConsole();
+ m_previousPauseOnExceptionsState = setPauseOnExceptionsState(V8DebuggerImpl::DontPauseOnExceptions);
+}
+
+V8DebuggerImpl::PauseOnExceptionsState InjectedScript::Scope::setPauseOnExceptionsState(V8DebuggerImpl::PauseOnExceptionsState newState)
+{
+ if (!m_debugger->enabled())
+ return newState;
+ V8DebuggerImpl::PauseOnExceptionsState presentState = m_debugger->getPauseOnExceptionsState();
+ if (presentState != newState)
+ m_debugger->setPauseOnExceptionsState(newState);
+ return presentState;
+}
+
+void InjectedScript::Scope::pretendUserGesture()
+{
+ DCHECK(!m_userGesture);
+ m_userGesture = true;
+ m_debugger->client()->beginUserGesture();
+}
+
+void InjectedScript::Scope::cleanup()
+{
+ v8::Local<v8::Object> global;
+ if (m_global.ToLocal(&global)) {
+ DCHECK(!m_context.IsEmpty());
+ global->DeletePrivate(m_context, m_extensionPrivate);
+ m_global = v8::MaybeLocal<v8::Object>();
+ }
+ if (!m_context.IsEmpty()) {
+ m_context->Exit();
+ m_context.Clear();
+ }
+}
+
+InjectedScript::Scope::~Scope()
+{
+ if (m_ignoreExceptionsAndMuteConsole) {
+ setPauseOnExceptionsState(m_previousPauseOnExceptionsState);
+ m_debugger->client()->unmuteConsole();
+ }
+ if (m_userGesture)
+ m_debugger->client()->endUserGesture();
+ cleanup();
+}
+
+InjectedScript::ContextScope::ContextScope(ErrorString* errorString, V8DebuggerImpl* debugger, int contextGroupId, int executionContextId)
+ : InjectedScript::Scope(errorString, debugger, contextGroupId)
+ , m_executionContextId(executionContextId)
+{
+}
+
+InjectedScript::ContextScope::~ContextScope()
+{
+}
+
+void InjectedScript::ContextScope::findInjectedScript(V8InspectorSessionImpl* session)
+{
+ m_injectedScript = session->findInjectedScript(m_errorString, m_executionContextId);
+}
+
+InjectedScript::ObjectScope::ObjectScope(ErrorString* errorString, V8DebuggerImpl* debugger, int contextGroupId, const String16& remoteObjectId)
+ : InjectedScript::Scope(errorString, debugger, contextGroupId)
+ , m_remoteObjectId(remoteObjectId)
+{
+}
+
+InjectedScript::ObjectScope::~ObjectScope()
+{
+}
+
+void InjectedScript::ObjectScope::findInjectedScript(V8InspectorSessionImpl* session)
+{
+ std::unique_ptr<RemoteObjectId> remoteId = RemoteObjectId::parse(m_errorString, m_remoteObjectId);
+ if (!remoteId)
+ return;
+ InjectedScript* injectedScript = session->findInjectedScript(m_errorString, remoteId.get());
+ if (!injectedScript)
+ return;
+ m_objectGroupName = injectedScript->objectGroupName(*remoteId);
+ if (!injectedScript->findObject(m_errorString, *remoteId, &m_object))
+ return;
+ m_injectedScript = injectedScript;
+}
+
+InjectedScript::CallFrameScope::CallFrameScope(ErrorString* errorString, V8DebuggerImpl* debugger, int contextGroupId, const String16& remoteObjectId)
+ : InjectedScript::Scope(errorString, debugger, contextGroupId)
+ , m_remoteCallFrameId(remoteObjectId)
+{
+}
+
+InjectedScript::CallFrameScope::~CallFrameScope()
+{
+}
+
+void InjectedScript::CallFrameScope::findInjectedScript(V8InspectorSessionImpl* session)
+{
+ std::unique_ptr<RemoteCallFrameId> remoteId = RemoteCallFrameId::parse(m_errorString, m_remoteCallFrameId);
+ if (!remoteId)
+ return;
+ m_frameOrdinal = static_cast<size_t>(remoteId->frameOrdinal());
+ m_injectedScript = session->findInjectedScript(m_errorString, remoteId.get());
+}
+
+} // namespace blink
diff --git a/deps/v8_inspector/platform/v8_inspector/InjectedScript.h b/deps/v8_inspector/platform/v8_inspector/InjectedScript.h
new file mode 100644
index 0000000000..8a33e73f53
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/InjectedScript.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef InjectedScript_h
+#define InjectedScript_h
+
+#include "platform/inspector_protocol/Allocator.h"
+#include "platform/inspector_protocol/TypeBuilder.h"
+#include "platform/v8_inspector/InjectedScriptNative.h"
+#include "platform/v8_inspector/InspectedContext.h"
+#include "platform/v8_inspector/V8DebuggerImpl.h"
+#include "wtf/PtrUtil.h"
+
+#include <v8.h>
+
+namespace blink {
+
+class RemoteObjectId;
+class V8FunctionCall;
+class V8InspectorSessionImpl;
+
+namespace protocol {
+class DictionaryValue;
+}
+
+using protocol::Maybe;
+
+class InjectedScript final {
+ PROTOCOL_DISALLOW_COPY(InjectedScript);
+public:
+ static std::unique_ptr<InjectedScript> create(InspectedContext*);
+ ~InjectedScript();
+
+ InspectedContext* context() const { return m_context; }
+
+ void getProperties(ErrorString*, v8::Local<v8::Object>, const String16& groupName, bool ownProperties, bool accessorPropertiesOnly, bool generatePreview, std::unique_ptr<protocol::Array<protocol::Runtime::PropertyDescriptor>>* result, Maybe<protocol::Runtime::ExceptionDetails>*);
+ void releaseObject(const String16& objectId);
+
+ std::unique_ptr<protocol::Runtime::RemoteObject> wrapObject(ErrorString*, v8::Local<v8::Value>, const String16& groupName, bool forceValueType = false, bool generatePreview = false) const;
+ bool wrapObjectProperty(ErrorString*, v8::Local<v8::Object>, v8::Local<v8::Value> key, const String16& groupName, bool forceValueType = false, bool generatePreview = false) const;
+ bool wrapPropertyInArray(ErrorString*, v8::Local<v8::Array>, v8::Local<v8::String> property, const String16& groupName, bool forceValueType = false, bool generatePreview = false) const;
+ bool wrapObjectsInArray(ErrorString*, v8::Local<v8::Array>, const String16& groupName, bool forceValueType = false, bool generatePreview = false) const;
+ std::unique_ptr<protocol::Runtime::RemoteObject> wrapTable(v8::Local<v8::Value> table, v8::Local<v8::Value> columns) const;
+
+ bool findObject(ErrorString*, const RemoteObjectId&, v8::Local<v8::Value>*) const;
+ String16 objectGroupName(const RemoteObjectId&) const;
+ void releaseObjectGroup(const String16&);
+ void setCustomObjectFormatterEnabled(bool);
+ v8::MaybeLocal<v8::Value> resolveCallArgument(ErrorString*, protocol::Runtime::CallArgument*);
+
+ std::unique_ptr<protocol::Runtime::ExceptionDetails> createExceptionDetails(v8::Local<v8::Message>);
+ void wrapEvaluateResult(ErrorString*,
+ v8::MaybeLocal<v8::Value> maybeResultValue,
+ const v8::TryCatch&,
+ const String16& objectGroup,
+ bool returnByValue,
+ bool generatePreview,
+ std::unique_ptr<protocol::Runtime::RemoteObject>* result,
+ Maybe<bool>* wasThrown,
+ Maybe<protocol::Runtime::ExceptionDetails>*);
+ v8::Local<v8::Value> lastEvaluationResult() const;
+
+ class Scope {
+ public:
+ bool initialize();
+ bool installCommandLineAPI();
+ void ignoreExceptionsAndMuteConsole();
+ void pretendUserGesture();
+ v8::Local<v8::Context> context() const { return m_context; }
+ InjectedScript* injectedScript() const { return m_injectedScript; }
+ const v8::TryCatch& tryCatch() const { return m_tryCatch; }
+
+ protected:
+ Scope(ErrorString*, V8DebuggerImpl*, int contextGroupId);
+ ~Scope();
+ virtual void findInjectedScript(V8InspectorSessionImpl*) = 0;
+
+ ErrorString* m_errorString;
+ V8DebuggerImpl* m_debugger;
+ int m_contextGroupId;
+ InjectedScript* m_injectedScript;
+
+ private:
+ void cleanup();
+ V8DebuggerImpl::PauseOnExceptionsState setPauseOnExceptionsState(V8DebuggerImpl::PauseOnExceptionsState);
+
+ v8::HandleScope m_handleScope;
+ v8::TryCatch m_tryCatch;
+ v8::Local<v8::Context> m_context;
+ v8::Local<v8::Private> m_extensionPrivate;
+ v8::MaybeLocal<v8::Object> m_global;
+ bool m_ignoreExceptionsAndMuteConsole;
+ V8DebuggerImpl::PauseOnExceptionsState m_previousPauseOnExceptionsState;
+ bool m_userGesture;
+ };
+
+ class ContextScope: public Scope {
+ PROTOCOL_DISALLOW_COPY(ContextScope);
+ public:
+ ContextScope(ErrorString*, V8DebuggerImpl*, int contextGroupId, int executionContextId);
+ ~ContextScope();
+ private:
+ void findInjectedScript(V8InspectorSessionImpl*) override;
+ int m_executionContextId;
+ };
+
+ class ObjectScope: public Scope {
+ PROTOCOL_DISALLOW_COPY(ObjectScope);
+ public:
+ ObjectScope(ErrorString*, V8DebuggerImpl*, int contextGroupId, const String16& remoteObjectId);
+ ~ObjectScope();
+ const String16& objectGroupName() const { return m_objectGroupName; }
+ v8::Local<v8::Value> object() const { return m_object; }
+ private:
+ void findInjectedScript(V8InspectorSessionImpl*) override;
+ String16 m_remoteObjectId;
+ String16 m_objectGroupName;
+ v8::Local<v8::Value> m_object;
+ };
+
+ class CallFrameScope: public Scope {
+ PROTOCOL_DISALLOW_COPY(CallFrameScope);
+ public:
+ CallFrameScope(ErrorString*, V8DebuggerImpl*, int contextGroupId, const String16& remoteCallFrameId);
+ ~CallFrameScope();
+ size_t frameOrdinal() const { return m_frameOrdinal; }
+ private:
+ void findInjectedScript(V8InspectorSessionImpl*) override;
+ String16 m_remoteCallFrameId;
+ size_t m_frameOrdinal;
+ };
+
+private:
+ InjectedScript(InspectedContext*, v8::Local<v8::Object>, std::unique_ptr<InjectedScriptNative>);
+ bool canAccessInspectedWindow() const;
+ v8::Local<v8::Value> v8Value() const;
+ v8::MaybeLocal<v8::Value> wrapValue(ErrorString*, v8::Local<v8::Value>, const String16& groupName, bool forceValueType, bool generatePreview) const;
+ v8::MaybeLocal<v8::Object> commandLineAPI(ErrorString*);
+
+ InspectedContext* m_context;
+ v8::Global<v8::Value> m_value;
+ v8::Global<v8::Value> m_lastEvaluationResult;
+ std::unique_ptr<InjectedScriptNative> m_native;
+ v8::Global<v8::Object> m_commandLineAPI;
+};
+
+} // namespace blink
+
+#endif
diff --git a/deps/v8_inspector/platform/v8_inspector/InjectedScriptNative.cpp b/deps/v8_inspector/platform/v8_inspector/InjectedScriptNative.cpp
new file mode 100644
index 0000000000..723eb867fa
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/InjectedScriptNative.cpp
@@ -0,0 +1,97 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/v8_inspector/InjectedScriptNative.h"
+
+#include "platform/inspector_protocol/Values.h"
+#include "wtf/Assertions.h"
+
+namespace blink {
+
+InjectedScriptNative::InjectedScriptNative(v8::Isolate* isolate)
+ : m_lastBoundObjectId(1)
+ , m_isolate(isolate)
+{
+}
+
+static const char privateKeyName[] = "v8-inspector#injectedScript";
+
+InjectedScriptNative::~InjectedScriptNative() { }
+
+void InjectedScriptNative::setOnInjectedScriptHost(v8::Local<v8::Object> injectedScriptHost)
+{
+ v8::HandleScope handleScope(m_isolate);
+ v8::Local<v8::External> external = v8::External::New(m_isolate, this);
+ v8::Local<v8::Private> privateKey = v8::Private::ForApi(m_isolate, v8::String::NewFromUtf8(m_isolate, privateKeyName, v8::NewStringType::kInternalized).ToLocalChecked());
+ injectedScriptHost->SetPrivate(m_isolate->GetCurrentContext(), privateKey, external);
+}
+
+InjectedScriptNative* InjectedScriptNative::fromInjectedScriptHost(v8::Local<v8::Object> injectedScriptObject)
+{
+ v8::Isolate* isolate = injectedScriptObject->GetIsolate();
+ v8::HandleScope handleScope(isolate);
+ v8::Local<v8::Context> context = isolate->GetCurrentContext();
+ v8::Local<v8::Private> privateKey = v8::Private::ForApi(isolate, v8::String::NewFromUtf8(isolate, privateKeyName, v8::NewStringType::kInternalized).ToLocalChecked());
+ v8::Local<v8::Value> value = injectedScriptObject->GetPrivate(context, privateKey).ToLocalChecked();
+ DCHECK(value->IsExternal());
+ v8::Local<v8::External> external = value.As<v8::External>();
+ return static_cast<InjectedScriptNative*>(external->Value());
+}
+
+int InjectedScriptNative::bind(v8::Local<v8::Value> value, const String16& groupName)
+{
+ if (m_lastBoundObjectId <= 0)
+ m_lastBoundObjectId = 1;
+ int id = m_lastBoundObjectId++;
+ m_idToWrappedObject.set(id, wrapUnique(new v8::Global<v8::Value>(m_isolate, value)));
+ addObjectToGroup(id, groupName);
+ return id;
+}
+
+void InjectedScriptNative::unbind(int id)
+{
+ m_idToWrappedObject.remove(id);
+ m_idToObjectGroupName.remove(id);
+}
+
+v8::Local<v8::Value> InjectedScriptNative::objectForId(int id)
+{
+ return m_idToWrappedObject.contains(id) ? m_idToWrappedObject.get(id)->Get(m_isolate) : v8::Local<v8::Value>();
+}
+
+void InjectedScriptNative::addObjectToGroup(int objectId, const String16& groupName)
+{
+ if (groupName.isEmpty())
+ return;
+ if (objectId <= 0)
+ return;
+ m_idToObjectGroupName.set(objectId, groupName);
+ auto it = m_nameToObjectGroup.find(groupName);
+ if (it == m_nameToObjectGroup.end()) {
+ m_nameToObjectGroup.set(groupName, protocol::Vector<int>());
+ it = m_nameToObjectGroup.find(groupName);
+ }
+ it->second->append(objectId);
+}
+
+void InjectedScriptNative::releaseObjectGroup(const String16& groupName)
+{
+ if (groupName.isEmpty())
+ return;
+ NameToObjectGroup::iterator groupIt = m_nameToObjectGroup.find(groupName);
+ if (groupIt == m_nameToObjectGroup.end())
+ return;
+ for (int id : *groupIt->second)
+ unbind(id);
+ m_nameToObjectGroup.remove(groupName);
+}
+
+String16 InjectedScriptNative::groupName(int objectId) const
+{
+ if (objectId <= 0)
+ return String16();
+ return m_idToObjectGroupName.get(objectId);
+}
+
+} // namespace blink
diff --git a/deps/v8_inspector/platform/v8_inspector/InjectedScriptNative.h b/deps/v8_inspector/platform/v8_inspector/InjectedScriptNative.h
new file mode 100644
index 0000000000..435bcdb8b7
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/InjectedScriptNative.h
@@ -0,0 +1,44 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef InjectedScriptNative_h
+#define InjectedScriptNative_h
+
+#include "platform/inspector_protocol/Collections.h"
+#include "platform/inspector_protocol/String16.h"
+#include "wtf/PtrUtil.h"
+#include <v8.h>
+
+namespace blink {
+
+class InjectedScriptNative final {
+public:
+ explicit InjectedScriptNative(v8::Isolate*);
+ ~InjectedScriptNative();
+
+ void setOnInjectedScriptHost(v8::Local<v8::Object>);
+ static InjectedScriptNative* fromInjectedScriptHost(v8::Local<v8::Object>);
+
+ int bind(v8::Local<v8::Value>, const String16& groupName);
+ void unbind(int id);
+ v8::Local<v8::Value> objectForId(int id);
+
+ void releaseObjectGroup(const String16& groupName);
+ String16 groupName(int objectId) const;
+
+private:
+ void addObjectToGroup(int objectId, const String16& groupName);
+
+ int m_lastBoundObjectId;
+ v8::Isolate* m_isolate;
+ protocol::HashMap<int, std::unique_ptr<v8::Global<v8::Value>>> m_idToWrappedObject;
+ typedef protocol::HashMap<int, String16> IdToObjectGroupName;
+ IdToObjectGroupName m_idToObjectGroupName;
+ typedef protocol::HashMap<String16, protocol::Vector<int>> NameToObjectGroup;
+ NameToObjectGroup m_nameToObjectGroup;
+};
+
+} // namespace blink
+
+#endif
diff --git a/deps/v8_inspector/platform/v8_inspector/InjectedScriptSource.js b/deps/v8_inspector/platform/v8_inspector/InjectedScriptSource.js
new file mode 100644
index 0000000000..bf0ed2bfd2
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/InjectedScriptSource.js
@@ -0,0 +1,1222 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+"use strict";
+
+/**
+ * @param {!InjectedScriptHostClass} InjectedScriptHost
+ * @param {!Window|!WorkerGlobalScope} inspectedGlobalObject
+ * @param {number} injectedScriptId
+ */
+(function (InjectedScriptHost, inspectedGlobalObject, injectedScriptId) {
+
+/**
+ * Protect against Object overwritten by the user code.
+ * @suppress {duplicate}
+ */
+var Object = /** @type {function(new:Object, *=)} */ ({}.constructor);
+
+/**
+ * @param {!Array.<T>} array
+ * @param {...} var_args
+ * @template T
+ */
+function push(array, var_args)
+{
+ for (var i = 1; i < arguments.length; ++i)
+ array[array.length] = arguments[i];
+}
+
+/**
+ * @param {(!Arguments.<T>|!NodeList)} array
+ * @param {number=} index
+ * @return {!Array.<T>}
+ * @template T
+ */
+function slice(array, index)
+{
+ var result = [];
+ for (var i = index || 0, j = 0; i < array.length; ++i, ++j)
+ result[j] = array[i];
+ return result;
+}
+
+/**
+ * @param {*} obj
+ * @return {string}
+ * @suppress {uselessCode}
+ */
+function toString(obj)
+{
+ // We don't use String(obj) because String16 could be overridden.
+ // Also the ("" + obj) expression may throw.
+ try {
+ return "" + obj;
+ } catch (e) {
+ var name = InjectedScriptHost.internalConstructorName(obj) || InjectedScriptHost.subtype(obj) || (typeof obj);
+ return "#<" + name + ">";
+ }
+}
+
+/**
+ * @param {*} obj
+ * @return {string}
+ */
+function toStringDescription(obj)
+{
+ if (typeof obj === "number" && obj === 0 && 1 / obj < 0)
+ return "-0"; // Negative zero.
+ return toString(obj);
+}
+
+/**
+ * @param {T} obj
+ * @return {T}
+ * @template T
+ */
+function nullifyObjectProto(obj)
+{
+ if (obj && typeof obj === "object")
+ obj.__proto__ = null;
+ return obj;
+}
+
+/**
+ * @param {number|string} obj
+ * @return {boolean}
+ */
+function isUInt32(obj)
+{
+ if (typeof obj === "number")
+ return obj >>> 0 === obj && (obj > 0 || 1 / obj > 0);
+ return "" + (obj >>> 0) === obj;
+}
+
+/**
+ * FireBug's array detection.
+ * @param {*} obj
+ * @return {boolean}
+ */
+function isArrayLike(obj)
+{
+ if (typeof obj !== "object")
+ return false;
+ try {
+ if (typeof obj.splice === "function") {
+ if (!InjectedScriptHost.suppressWarningsAndCallFunction(Object.prototype.hasOwnProperty, obj, ["length"]))
+ return false;
+ var len = obj.length;
+ return typeof len === "number" && isUInt32(len);
+ }
+ } catch (e) {
+ }
+ return false;
+}
+
+/**
+ * @param {number} a
+ * @param {number} b
+ * @return {number}
+ */
+function max(a, b)
+{
+ return a > b ? a : b;
+}
+
+/**
+ * FIXME: Remove once ES6 is supported natively by JS compiler.
+ * @param {*} obj
+ * @return {boolean}
+ */
+function isSymbol(obj)
+{
+ var type = typeof obj;
+ return (type === "symbol");
+}
+
+/**
+ * DOM Attributes which have observable side effect on getter, in the form of
+ * {interfaceName1: {attributeName1: true,
+ * attributeName2: true,
+ * ...},
+ * interfaceName2: {...},
+ * ...}
+ * @type {!Object<string, !Object<string, boolean>>}
+ * @const
+ */
+var domAttributesWithObservableSideEffectOnGet = nullifyObjectProto({});
+domAttributesWithObservableSideEffectOnGet["Request"] = nullifyObjectProto({});
+domAttributesWithObservableSideEffectOnGet["Request"]["body"] = true;
+domAttributesWithObservableSideEffectOnGet["Response"] = nullifyObjectProto({});
+domAttributesWithObservableSideEffectOnGet["Response"]["body"] = true;
+
+/**
+ * @param {!Object} object
+ * @param {string} attribute
+ * @return {boolean}
+ */
+function doesAttributeHaveObservableSideEffectOnGet(object, attribute)
+{
+ for (var interfaceName in domAttributesWithObservableSideEffectOnGet) {
+ var isInstance = InjectedScriptHost.suppressWarningsAndCallFunction(function(object, interfaceName) {
+ return /* suppressBlacklist */ typeof inspectedGlobalObject[interfaceName] === "function" && object instanceof inspectedGlobalObject[interfaceName];
+ }, null, [object, interfaceName]);
+ if (isInstance) {
+ return attribute in domAttributesWithObservableSideEffectOnGet[interfaceName];
+ }
+ }
+ return false;
+}
+
+/**
+ * @constructor
+ */
+var InjectedScript = function()
+{
+}
+
+/**
+ * @type {!Object.<string, boolean>}
+ * @const
+ */
+InjectedScript.primitiveTypes = {
+ "undefined": true,
+ "boolean": true,
+ "number": true,
+ "string": true,
+ __proto__: null
+}
+
+InjectedScript.prototype = {
+ /**
+ * @param {*} object
+ * @return {boolean}
+ */
+ isPrimitiveValue: function(object)
+ {
+ // FIXME(33716): typeof document.all is always 'undefined'.
+ return InjectedScript.primitiveTypes[typeof object] && !this._isHTMLAllCollection(object);
+ },
+
+ /**
+ * @param {*} object
+ * @param {string} groupName
+ * @param {boolean} canAccessInspectedGlobalObject
+ * @param {boolean} forceValueType
+ * @param {boolean} generatePreview
+ * @return {!RuntimeAgent.RemoteObject}
+ */
+ wrapObject: function(object, groupName, canAccessInspectedGlobalObject, forceValueType, generatePreview)
+ {
+ if (canAccessInspectedGlobalObject)
+ return this._wrapObject(object, groupName, forceValueType, generatePreview);
+ return this._fallbackWrapper(object);
+ },
+
+ /**
+ * @param {!Array<!Object>} array
+ * @param {string} property
+ * @param {string} groupName
+ * @param {boolean} canAccessInspectedGlobalObject
+ * @param {boolean} forceValueType
+ * @param {boolean} generatePreview
+ */
+ wrapPropertyInArray: function(array, property, groupName, canAccessInspectedGlobalObject, forceValueType, generatePreview)
+ {
+ for (var i = 0; i < array.length; ++i) {
+ if (typeof array[i] === "object" && property in array[i])
+ array[i][property] = this.wrapObject(array[i][property], groupName, canAccessInspectedGlobalObject, forceValueType, generatePreview);
+ }
+ },
+
+ /**
+ * @param {!Array<*>} array
+ * @param {string} groupName
+ * @param {boolean} canAccessInspectedGlobalObject
+ * @param {boolean} forceValueType
+ * @param {boolean} generatePreview
+ */
+ wrapObjectsInArray: function(array, groupName, canAccessInspectedGlobalObject, forceValueType, generatePreview)
+ {
+ for (var i = 0; i < array.length; ++i)
+ array[i] = this.wrapObject(array[i], groupName, canAccessInspectedGlobalObject, forceValueType, generatePreview);
+ },
+
+ /**
+ * @param {*} object
+ * @return {!RuntimeAgent.RemoteObject}
+ */
+ _fallbackWrapper: function(object)
+ {
+ var result = { __proto__: null };
+ result.type = typeof object;
+ if (this.isPrimitiveValue(object))
+ result.value = object;
+ else
+ result.description = toString(object);
+ return /** @type {!RuntimeAgent.RemoteObject} */ (result);
+ },
+
+ /**
+ * @param {boolean} canAccessInspectedGlobalObject
+ * @param {!Object} table
+ * @param {!Array.<string>|string|boolean} columns
+ * @return {!RuntimeAgent.RemoteObject}
+ */
+ wrapTable: function(canAccessInspectedGlobalObject, table, columns)
+ {
+ if (!canAccessInspectedGlobalObject)
+ return this._fallbackWrapper(table);
+ var columnNames = null;
+ if (typeof columns === "string")
+ columns = [columns];
+ if (InjectedScriptHost.subtype(columns) === "array") {
+ columnNames = [];
+ for (var i = 0; i < columns.length; ++i)
+ columnNames[i] = toString(columns[i]);
+ }
+ return this._wrapObject(table, "console", false, true, columnNames, true);
+ },
+
+ /**
+ * This method cannot throw.
+ * @param {*} object
+ * @param {string=} objectGroupName
+ * @param {boolean=} forceValueType
+ * @param {boolean=} generatePreview
+ * @param {?Array.<string>=} columnNames
+ * @param {boolean=} isTable
+ * @param {boolean=} doNotBind
+ * @param {*=} customObjectConfig
+ * @return {!RuntimeAgent.RemoteObject}
+ * @suppress {checkTypes}
+ */
+ _wrapObject: function(object, objectGroupName, forceValueType, generatePreview, columnNames, isTable, doNotBind, customObjectConfig)
+ {
+ try {
+ return new InjectedScript.RemoteObject(object, objectGroupName, doNotBind, forceValueType, generatePreview, columnNames, isTable, undefined, customObjectConfig);
+ } catch (e) {
+ try {
+ var description = injectedScript._describe(e);
+ } catch (ex) {
+ var description = "<failed to convert exception to string>";
+ }
+ return new InjectedScript.RemoteObject(description);
+ }
+ },
+
+ /**
+ * @param {!Object|symbol} object
+ * @param {string=} objectGroupName
+ * @return {string}
+ */
+ _bind: function(object, objectGroupName)
+ {
+ var id = InjectedScriptHost.bind(object, objectGroupName || "");
+ return "{\"injectedScriptId\":" + injectedScriptId + ",\"id\":" + id + "}";
+ },
+
+ /**
+ * @param {!Object} object
+ * @param {string} objectGroupName
+ * @param {boolean} ownProperties
+ * @param {boolean} accessorPropertiesOnly
+ * @param {boolean} generatePreview
+ * @return {!Array<!RuntimeAgent.PropertyDescriptor>|boolean}
+ */
+ getProperties: function(object, objectGroupName, ownProperties, accessorPropertiesOnly, generatePreview)
+ {
+ var descriptors = [];
+ var iter = this._propertyDescriptors(object, ownProperties, accessorPropertiesOnly, undefined);
+ // Go over properties, wrap object values.
+ for (var descriptor of iter) {
+ if ("get" in descriptor)
+ descriptor.get = this._wrapObject(descriptor.get, objectGroupName);
+ if ("set" in descriptor)
+ descriptor.set = this._wrapObject(descriptor.set, objectGroupName);
+ if ("value" in descriptor)
+ descriptor.value = this._wrapObject(descriptor.value, objectGroupName, false, generatePreview);
+ if (!("configurable" in descriptor))
+ descriptor.configurable = false;
+ if (!("enumerable" in descriptor))
+ descriptor.enumerable = false;
+ if ("symbol" in descriptor)
+ descriptor.symbol = this._wrapObject(descriptor.symbol, objectGroupName);
+ push(descriptors, descriptor);
+ }
+ return descriptors;
+ },
+
+ /**
+ * @param {!Object} object
+ * @param {boolean=} ownProperties
+ * @param {boolean=} accessorPropertiesOnly
+ * @param {?Array.<string>=} propertyNamesOnly
+ */
+ _propertyDescriptors: function*(object, ownProperties, accessorPropertiesOnly, propertyNamesOnly)
+ {
+ var propertyProcessed = { __proto__: null };
+
+ /**
+ * @param {?Object} o
+ * @param {!Iterable<string|symbol|number>|!Array<string|number|symbol>} properties
+ */
+ function* process(o, properties)
+ {
+ for (var property of properties) {
+ var name;
+ if (isSymbol(property))
+ name = /** @type {string} */ (injectedScript._describe(property));
+ else
+ name = typeof property === "number" ? ("" + property) : /** @type {string} */(property);
+
+ if (propertyProcessed[property])
+ continue;
+
+ try {
+ propertyProcessed[property] = true;
+ var descriptor = nullifyObjectProto(InjectedScriptHost.suppressWarningsAndCallFunction(Object.getOwnPropertyDescriptor, Object, [o, property]));
+ if (descriptor) {
+ if (accessorPropertiesOnly && !("get" in descriptor || "set" in descriptor))
+ continue;
+ if ("get" in descriptor && "set" in descriptor && name != "__proto__" && InjectedScriptHost.formatAccessorsAsProperties(object) && !doesAttributeHaveObservableSideEffectOnGet(object, name)) {
+ descriptor.value = InjectedScriptHost.suppressWarningsAndCallFunction(function(attribute) { return this[attribute]; }, object, [property]);
+ descriptor.isOwn = true;
+ delete descriptor.get;
+ delete descriptor.set;
+ }
+ } else {
+ // Not all bindings provide proper descriptors. Fall back to the writable, configurable property.
+ if (accessorPropertiesOnly)
+ continue;
+ try {
+ descriptor = { name: name, value: o[property], writable: false, configurable: false, enumerable: false, __proto__: null };
+ if (o === object)
+ descriptor.isOwn = true;
+ yield descriptor;
+ } catch (e) {
+ // Silent catch.
+ }
+ continue;
+ }
+ } catch (e) {
+ if (accessorPropertiesOnly)
+ continue;
+ var descriptor = { __proto__: null };
+ descriptor.value = e;
+ descriptor.wasThrown = true;
+ }
+
+ descriptor.name = name;
+ if (o === object)
+ descriptor.isOwn = true;
+ if (isSymbol(property))
+ descriptor.symbol = property;
+ yield descriptor;
+ }
+ }
+
+ if (propertyNamesOnly) {
+ for (var i = 0; i < propertyNamesOnly.length; ++i) {
+ var name = propertyNamesOnly[i];
+ for (var o = object; this._isDefined(o); o = InjectedScriptHost.prototype(o)) {
+ if (InjectedScriptHost.suppressWarningsAndCallFunction(Object.prototype.hasOwnProperty, o, [name])) {
+ for (var descriptor of process(o, [name]))
+ yield descriptor;
+ break;
+ }
+ if (ownProperties)
+ break;
+ }
+ }
+ return;
+ }
+
+ /**
+ * @param {number} length
+ */
+ function* arrayIndexNames(length)
+ {
+ for (var i = 0; i < length; ++i)
+ yield "" + i;
+ }
+
+ var skipGetOwnPropertyNames;
+ try {
+ skipGetOwnPropertyNames = InjectedScriptHost.isTypedArray(object) && object.length > 500000;
+ } catch (e) {
+ }
+
+ for (var o = object; this._isDefined(o); o = InjectedScriptHost.prototype(o)) {
+ if (InjectedScriptHost.subtype(o) === "proxy")
+ continue;
+ if (skipGetOwnPropertyNames && o === object) {
+ // Avoid OOM crashes from getting all own property names of a large TypedArray.
+ for (var descriptor of process(o, arrayIndexNames(o.length)))
+ yield descriptor;
+ } else {
+ // First call Object.keys() to enforce ordering of the property descriptors.
+ for (var descriptor of process(o, Object.keys(/** @type {!Object} */ (o))))
+ yield descriptor;
+ for (var descriptor of process(o, Object.getOwnPropertyNames(/** @type {!Object} */ (o))))
+ yield descriptor;
+ }
+ if (Object.getOwnPropertySymbols) {
+ for (var descriptor of process(o, Object.getOwnPropertySymbols(/** @type {!Object} */ (o))))
+ yield descriptor;
+ }
+ if (ownProperties) {
+ var proto = InjectedScriptHost.prototype(o);
+ if (proto && !accessorPropertiesOnly)
+ yield { name: "__proto__", value: proto, writable: true, configurable: true, enumerable: false, isOwn: true, __proto__: null };
+ break;
+ }
+ }
+ },
+
+ /**
+ * @param {string|undefined} objectGroupName
+ * @param {*} jsonMLObject
+ * @throws {string} error message
+ */
+ _substituteObjectTagsInCustomPreview: function(objectGroupName, jsonMLObject)
+ {
+ var maxCustomPreviewRecursionDepth = 20;
+ this._customPreviewRecursionDepth = (this._customPreviewRecursionDepth || 0) + 1
+ try {
+ if (this._customPreviewRecursionDepth >= maxCustomPreviewRecursionDepth)
+ throw new Error("Too deep hierarchy of inlined custom previews");
+
+ if (!isArrayLike(jsonMLObject))
+ return;
+
+ if (jsonMLObject[0] === "object") {
+ var attributes = jsonMLObject[1];
+ var originObject = attributes["object"];
+ var config = attributes["config"];
+ if (typeof originObject === "undefined")
+ throw new Error("Illegal format: obligatory attribute \"object\" isn't specified");
+
+ jsonMLObject[1] = this._wrapObject(originObject, objectGroupName, false, false, null, false, false, config);
+ return;
+ }
+
+ for (var i = 0; i < jsonMLObject.length; ++i)
+ this._substituteObjectTagsInCustomPreview(objectGroupName, jsonMLObject[i]);
+ } finally {
+ this._customPreviewRecursionDepth--;
+ }
+ },
+
+ /**
+ * @param {!Object} nativeCommandLineAPI
+ * @return {!Object}
+ */
+ installCommandLineAPI: function(nativeCommandLineAPI)
+ {
+ // NOTE: This list contains only not native Command Line API methods. For full list: V8Console.
+ // NOTE: Argument names of these methods will be printed in the console, so use pretty names!
+ var members = [ "$", "$$", "$x", "monitorEvents", "unmonitorEvents", "getEventListeners" ];
+ for (var member of members)
+ nativeCommandLineAPI[member] = CommandLineAPIImpl[member];
+ var functionToStringMap = new Map([
+ ["$", "function $(selector, [startNode]) { [Command Line API] }"],
+ ["$$", "function $$(selector, [startNode]) { [Command Line API] }"],
+ ["$x", "function $x(xpath, [startNode]) { [Command Line API] }"],
+ ["monitorEvents", "function monitorEvents(object, [types]) { [Command Line API] }"],
+ ["unmonitorEvents", "function unmonitorEvents(object, [types]) { [Command Line API] }"],
+ ["getEventListeners", "function getEventListeners(node) { [Command Line API] }"]
+ ]);
+ for (let entry of functionToStringMap)
+ nativeCommandLineAPI[entry[0]].toString = (() => entry[1]);
+ return nativeCommandLineAPI;
+ },
+
+ /**
+ * @param {*} object
+ * @return {boolean}
+ */
+ _isDefined: function(object)
+ {
+ return !!object || this._isHTMLAllCollection(object);
+ },
+
+ /**
+ * @param {*} object
+ * @return {boolean}
+ */
+ _isHTMLAllCollection: function(object)
+ {
+ // document.all is reported as undefined, but we still want to process it.
+ return (typeof object === "undefined") && !!InjectedScriptHost.subtype(object);
+ },
+
+ /**
+ * @param {*} obj
+ * @return {?string}
+ */
+ _subtype: function(obj)
+ {
+ if (obj === null)
+ return "null";
+
+ if (this.isPrimitiveValue(obj))
+ return null;
+
+ var subtype = InjectedScriptHost.subtype(obj);
+ if (subtype)
+ return subtype;
+
+ if (isArrayLike(obj))
+ return "array";
+
+ // If owning frame has navigated to somewhere else window properties will be undefined.
+ return null;
+ },
+
+ /**
+ * @param {*} obj
+ * @return {?string}
+ */
+ _describe: function(obj)
+ {
+ if (this.isPrimitiveValue(obj))
+ return null;
+
+ var subtype = this._subtype(obj);
+
+ if (subtype === "regexp")
+ return toString(obj);
+
+ if (subtype === "date")
+ return toString(obj);
+
+ if (subtype === "node") {
+ var description = obj.nodeName.toLowerCase();
+ switch (obj.nodeType) {
+ case 1 /* Node.ELEMENT_NODE */:
+ description += obj.id ? "#" + obj.id : "";
+ var className = obj.className;
+ description += (className && typeof className === "string") ? "." + className.trim().replace(/\s+/g, ".") : "";
+ break;
+ case 10 /*Node.DOCUMENT_TYPE_NODE */:
+ description = "<!DOCTYPE " + description + ">";
+ break;
+ }
+ return description;
+ }
+
+ if (subtype === "proxy")
+ return "Proxy";
+
+ var className = InjectedScriptHost.internalConstructorName(obj);
+ if (subtype === "array") {
+ if (typeof obj.length === "number")
+ className += "[" + obj.length + "]";
+ return className;
+ }
+
+ if (typeof obj === "function")
+ return toString(obj);
+
+ if (isSymbol(obj)) {
+ try {
+ return /** @type {string} */ (InjectedScriptHost.suppressWarningsAndCallFunction(Symbol.prototype.toString, obj)) || "Symbol";
+ } catch (e) {
+ return "Symbol";
+ }
+ }
+
+ if (InjectedScriptHost.subtype(obj) === "error") {
+ try {
+ var stack = obj.stack;
+ var message = obj.message && obj.message.length ? ": " + obj.message : "";
+ var firstCallFrame = /^\s+at\s/m.exec(stack);
+ var stackMessageEnd = firstCallFrame ? firstCallFrame.index : -1;
+ if (stackMessageEnd !== -1) {
+ var stackTrace = stack.substr(stackMessageEnd);
+ return className + message + "\n" + stackTrace;
+ }
+ return className + message;
+ } catch(e) {
+ }
+ }
+
+ return className;
+ },
+
+ /**
+ * @param {boolean} enabled
+ */
+ setCustomObjectFormatterEnabled: function(enabled)
+ {
+ this._customObjectFormatterEnabled = enabled;
+ }
+}
+
+/**
+ * @type {!InjectedScript}
+ * @const
+ */
+var injectedScript = new InjectedScript();
+
+/**
+ * @constructor
+ * @param {*} object
+ * @param {string=} objectGroupName
+ * @param {boolean=} doNotBind
+ * @param {boolean=} forceValueType
+ * @param {boolean=} generatePreview
+ * @param {?Array.<string>=} columnNames
+ * @param {boolean=} isTable
+ * @param {boolean=} skipEntriesPreview
+ * @param {*=} customObjectConfig
+ */
+InjectedScript.RemoteObject = function(object, objectGroupName, doNotBind, forceValueType, generatePreview, columnNames, isTable, skipEntriesPreview, customObjectConfig)
+{
+ this.type = typeof object;
+ if (this.type === "undefined" && injectedScript._isHTMLAllCollection(object))
+ this.type = "object";
+
+ if (injectedScript.isPrimitiveValue(object) || object === null || forceValueType) {
+ // We don't send undefined values over JSON.
+ if (this.type !== "undefined")
+ this.value = object;
+
+ // Null object is object with 'null' subtype.
+ if (object === null)
+ this.subtype = "null";
+
+ // Provide user-friendly number values.
+ if (this.type === "number") {
+ this.description = toStringDescription(object);
+ // Override "value" property for values that can not be JSON-stringified.
+ switch (this.description) {
+ case "NaN":
+ case "Infinity":
+ case "-Infinity":
+ case "-0":
+ this.value = this.description;
+ break;
+ }
+ }
+
+ return;
+ }
+
+ object = /** @type {!Object} */ (object);
+
+ if (!doNotBind)
+ this.objectId = injectedScript._bind(object, objectGroupName);
+ var subtype = injectedScript._subtype(object);
+ if (subtype)
+ this.subtype = subtype;
+ var className = InjectedScriptHost.internalConstructorName(object);
+ if (className)
+ this.className = className;
+ this.description = injectedScript._describe(object);
+
+ if (generatePreview && this.type === "object") {
+ if (this.subtype === "proxy")
+ this.preview = this._generatePreview(InjectedScriptHost.proxyTargetValue(object), undefined, columnNames, isTable, skipEntriesPreview);
+ else if (this.subtype !== "node")
+ this.preview = this._generatePreview(object, undefined, columnNames, isTable, skipEntriesPreview);
+ }
+
+ if (injectedScript._customObjectFormatterEnabled) {
+ var customPreview = this._customPreview(object, objectGroupName, customObjectConfig);
+ if (customPreview)
+ this.customPreview = customPreview;
+ }
+}
+
+InjectedScript.RemoteObject.prototype = {
+
+ /**
+ * @param {*} object
+ * @param {string=} objectGroupName
+ * @param {*=} customObjectConfig
+ * @return {?RuntimeAgent.CustomPreview}
+ */
+ _customPreview: function(object, objectGroupName, customObjectConfig)
+ {
+ /**
+ * @param {!Error} error
+ */
+ function logError(error)
+ {
+ Promise.resolve().then(inspectedGlobalObject.console.error.bind(inspectedGlobalObject.console, "Custom Formatter Failed: " + error.message));
+ }
+
+ /**
+ * @suppressReceiverCheck
+ * @param {*} object
+ * @param {*=} customObjectConfig
+ * @return {*}
+ */
+ function wrap(object, customObjectConfig)
+ {
+ return InjectedScriptHost.suppressWarningsAndCallFunction(injectedScript._wrapObject, injectedScript, [ object, objectGroupName, false, false, null, false, false, customObjectConfig ]);
+ }
+
+ try {
+ var formatters = inspectedGlobalObject["devtoolsFormatters"];
+ if (!formatters || !isArrayLike(formatters))
+ return null;
+
+ for (var i = 0; i < formatters.length; ++i) {
+ try {
+ var formatted = formatters[i].header(object, customObjectConfig);
+ if (!formatted)
+ continue;
+
+ var hasBody = formatters[i].hasBody(object, customObjectConfig);
+ injectedScript._substituteObjectTagsInCustomPreview(objectGroupName, formatted);
+ var formatterObjectId = injectedScript._bind(formatters[i], objectGroupName);
+ var bindRemoteObjectFunctionId = injectedScript._bind(wrap, objectGroupName);
+ var result = {header: JSON.stringify(formatted), hasBody: !!hasBody, formatterObjectId: formatterObjectId, bindRemoteObjectFunctionId: bindRemoteObjectFunctionId};
+ if (customObjectConfig)
+ result["configObjectId"] = injectedScript._bind(customObjectConfig, objectGroupName);
+ return result;
+ } catch (e) {
+ logError(e);
+ }
+ }
+ } catch (e) {
+ logError(e);
+ }
+ return null;
+ },
+
+ /**
+ * @return {!RuntimeAgent.ObjectPreview} preview
+ */
+ _createEmptyPreview: function()
+ {
+ var preview = {
+ type: /** @type {!RuntimeAgent.ObjectPreviewType.<string>} */ (this.type),
+ description: this.description || toStringDescription(this.value),
+ overflow: false,
+ properties: [],
+ __proto__: null
+ };
+ if (this.subtype)
+ preview.subtype = /** @type {!RuntimeAgent.ObjectPreviewSubtype.<string>} */ (this.subtype);
+ return preview;
+ },
+
+ /**
+ * @param {!Object} object
+ * @param {?Array.<string>=} firstLevelKeys
+ * @param {?Array.<string>=} secondLevelKeys
+ * @param {boolean=} isTable
+ * @param {boolean=} skipEntriesPreview
+ * @return {!RuntimeAgent.ObjectPreview} preview
+ */
+ _generatePreview: function(object, firstLevelKeys, secondLevelKeys, isTable, skipEntriesPreview)
+ {
+ var preview = this._createEmptyPreview();
+ var firstLevelKeysCount = firstLevelKeys ? firstLevelKeys.length : 0;
+
+ var propertiesThreshold = {
+ properties: isTable ? 1000 : max(5, firstLevelKeysCount),
+ indexes: isTable ? 1000 : max(100, firstLevelKeysCount),
+ __proto__: null
+ };
+
+ try {
+ var descriptors = injectedScript._propertyDescriptors(object, undefined, undefined, firstLevelKeys);
+
+ this._appendPropertyDescriptors(preview, descriptors, propertiesThreshold, secondLevelKeys, isTable);
+ if (propertiesThreshold.indexes < 0 || propertiesThreshold.properties < 0)
+ return preview;
+
+ // Add internal properties to preview.
+ var rawInternalProperties = InjectedScriptHost.getInternalProperties(object) || [];
+ var internalProperties = [];
+ for (var i = 0; i < rawInternalProperties.length; i += 2) {
+ push(internalProperties, {
+ name: rawInternalProperties[i],
+ value: rawInternalProperties[i + 1],
+ isOwn: true,
+ enumerable: true,
+ __proto__: null
+ });
+ }
+ this._appendPropertyDescriptors(preview, internalProperties, propertiesThreshold, secondLevelKeys, isTable);
+
+ if (this.subtype === "map" || this.subtype === "set" || this.subtype === "iterator")
+ this._appendEntriesPreview(object, preview, skipEntriesPreview);
+
+ } catch (e) {}
+
+ return preview;
+ },
+
+ /**
+ * @param {!RuntimeAgent.ObjectPreview} preview
+ * @param {!Array.<*>|!Iterable.<*>} descriptors
+ * @param {!Object} propertiesThreshold
+ * @param {?Array.<string>=} secondLevelKeys
+ * @param {boolean=} isTable
+ */
+ _appendPropertyDescriptors: function(preview, descriptors, propertiesThreshold, secondLevelKeys, isTable)
+ {
+ for (var descriptor of descriptors) {
+ if (propertiesThreshold.indexes < 0 || propertiesThreshold.properties < 0)
+ break;
+ if (!descriptor || descriptor.wasThrown)
+ continue;
+
+ var name = descriptor.name;
+
+ // Ignore __proto__ property.
+ if (name === "__proto__")
+ continue;
+
+ // Ignore length property of array.
+ if (this.subtype === "array" && name === "length")
+ continue;
+
+ // Ignore size property of map, set.
+ if ((this.subtype === "map" || this.subtype === "set") && name === "size")
+ continue;
+
+ // Never preview prototype properties.
+ if (!descriptor.isOwn)
+ continue;
+
+ // Ignore computed properties.
+ if (!("value" in descriptor))
+ continue;
+
+ var value = descriptor.value;
+ var type = typeof value;
+
+ // Never render functions in object preview.
+ if (type === "function" && (this.subtype !== "array" || !isUInt32(name)))
+ continue;
+
+ // Special-case HTMLAll.
+ if (type === "undefined" && injectedScript._isHTMLAllCollection(value))
+ type = "object";
+
+ // Render own properties.
+ if (value === null) {
+ this._appendPropertyPreview(preview, { name: name, type: "object", subtype: "null", value: "null", __proto__: null }, propertiesThreshold);
+ continue;
+ }
+
+ var maxLength = 100;
+ if (InjectedScript.primitiveTypes[type]) {
+ if (type === "string" && value.length > maxLength)
+ value = this._abbreviateString(value, maxLength, true);
+ this._appendPropertyPreview(preview, { name: name, type: type, value: toStringDescription(value), __proto__: null }, propertiesThreshold);
+ continue;
+ }
+
+ var property = { name: name, type: type, __proto__: null };
+ var subtype = injectedScript._subtype(value);
+ if (subtype)
+ property.subtype = subtype;
+
+ if (secondLevelKeys === null || secondLevelKeys) {
+ var subPreview = this._generatePreview(value, secondLevelKeys || undefined, undefined, isTable);
+ property.valuePreview = subPreview;
+ if (subPreview.overflow)
+ preview.overflow = true;
+ } else {
+ var description = "";
+ if (type !== "function")
+ description = this._abbreviateString(/** @type {string} */ (injectedScript._describe(value)), maxLength, subtype === "regexp");
+ property.value = description;
+ }
+ this._appendPropertyPreview(preview, property, propertiesThreshold);
+ }
+ },
+
+ /**
+ * @param {!RuntimeAgent.ObjectPreview} preview
+ * @param {!Object} property
+ * @param {!Object} propertiesThreshold
+ */
+ _appendPropertyPreview: function(preview, property, propertiesThreshold)
+ {
+ if (toString(property.name >>> 0) === property.name)
+ propertiesThreshold.indexes--;
+ else
+ propertiesThreshold.properties--;
+ if (propertiesThreshold.indexes < 0 || propertiesThreshold.properties < 0) {
+ preview.overflow = true;
+ } else {
+ push(preview.properties, property);
+ }
+ },
+
+ /**
+ * @param {!Object} object
+ * @param {!RuntimeAgent.ObjectPreview} preview
+ * @param {boolean=} skipEntriesPreview
+ */
+ _appendEntriesPreview: function(object, preview, skipEntriesPreview)
+ {
+ var entries = InjectedScriptHost.collectionEntries(object);
+ if (!entries)
+ return;
+ if (skipEntriesPreview) {
+ if (entries.length)
+ preview.overflow = true;
+ return;
+ }
+ preview.entries = [];
+ var entriesThreshold = 5;
+ for (var i = 0; i < entries.length; ++i) {
+ if (preview.entries.length >= entriesThreshold) {
+ preview.overflow = true;
+ break;
+ }
+ var entry = nullifyObjectProto(entries[i]);
+ var previewEntry = {
+ value: generateValuePreview(entry.value),
+ __proto__: null
+ };
+ if ("key" in entry)
+ previewEntry.key = generateValuePreview(entry.key);
+ push(preview.entries, previewEntry);
+ }
+
+ /**
+ * @param {*} value
+ * @return {!RuntimeAgent.ObjectPreview}
+ */
+ function generateValuePreview(value)
+ {
+ var remoteObject = new InjectedScript.RemoteObject(value, undefined, true, undefined, true, undefined, undefined, true);
+ var valuePreview = remoteObject.preview || remoteObject._createEmptyPreview();
+ return valuePreview;
+ }
+ },
+
+ /**
+ * @param {string} string
+ * @param {number} maxLength
+ * @param {boolean=} middle
+ * @return {string}
+ */
+ _abbreviateString: function(string, maxLength, middle)
+ {
+ if (string.length <= maxLength)
+ return string;
+ if (middle) {
+ var leftHalf = maxLength >> 1;
+ var rightHalf = maxLength - leftHalf - 1;
+ return string.substr(0, leftHalf) + "\u2026" + string.substr(string.length - rightHalf, rightHalf);
+ }
+ return string.substr(0, maxLength) + "\u2026";
+ },
+
+ __proto__: null
+}
+
+var CommandLineAPIImpl = { __proto__: null }
+
+/**
+ * @param {string} selector
+ * @param {!Node=} opt_startNode
+ * @return {*}
+ */
+CommandLineAPIImpl.$ = function (selector, opt_startNode)
+{
+ if (CommandLineAPIImpl._canQuerySelectorOnNode(opt_startNode))
+ return opt_startNode.querySelector(selector);
+
+ return inspectedGlobalObject.document.querySelector(selector);
+}
+
+/**
+ * @param {string} selector
+ * @param {!Node=} opt_startNode
+ * @return {*}
+ */
+CommandLineAPIImpl.$$ = function (selector, opt_startNode)
+{
+ if (CommandLineAPIImpl._canQuerySelectorOnNode(opt_startNode))
+ return slice(opt_startNode.querySelectorAll(selector));
+ return slice(inspectedGlobalObject.document.querySelectorAll(selector));
+}
+
+/**
+ * @param {!Node=} node
+ * @return {boolean}
+ */
+CommandLineAPIImpl._canQuerySelectorOnNode = function(node)
+{
+ return !!node && InjectedScriptHost.subtype(node) === "node" && (node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.DOCUMENT_NODE || node.nodeType === Node.DOCUMENT_FRAGMENT_NODE);
+}
+
+/**
+ * @param {string} xpath
+ * @param {!Node=} opt_startNode
+ * @return {*}
+ */
+CommandLineAPIImpl.$x = function(xpath, opt_startNode)
+{
+ var doc = (opt_startNode && opt_startNode.ownerDocument) || inspectedGlobalObject.document;
+ var result = doc.evaluate(xpath, opt_startNode || doc, null, XPathResult.ANY_TYPE, null);
+ switch (result.resultType) {
+ case XPathResult.NUMBER_TYPE:
+ return result.numberValue;
+ case XPathResult.STRING_TYPE:
+ return result.stringValue;
+ case XPathResult.BOOLEAN_TYPE:
+ return result.booleanValue;
+ default:
+ var nodes = [];
+ var node;
+ while (node = result.iterateNext())
+ push(nodes, node);
+ return nodes;
+ }
+}
+
+/**
+ * @param {!Object} object
+ * @param {!Array.<string>|string=} opt_types
+ */
+CommandLineAPIImpl.monitorEvents = function(object, opt_types)
+{
+ if (!object || !object.addEventListener || !object.removeEventListener)
+ return;
+ var types = CommandLineAPIImpl._normalizeEventTypes(opt_types);
+ for (var i = 0; i < types.length; ++i) {
+ object.removeEventListener(types[i], CommandLineAPIImpl._logEvent, false);
+ object.addEventListener(types[i], CommandLineAPIImpl._logEvent, false);
+ }
+}
+
+/**
+ * @param {!Object} object
+ * @param {!Array.<string>|string=} opt_types
+ */
+CommandLineAPIImpl.unmonitorEvents = function(object, opt_types)
+{
+ if (!object || !object.addEventListener || !object.removeEventListener)
+ return;
+ var types = CommandLineAPIImpl._normalizeEventTypes(opt_types);
+ for (var i = 0; i < types.length; ++i)
+ object.removeEventListener(types[i], CommandLineAPIImpl._logEvent, false);
+}
+
+/**
+ * @param {!Node} node
+ * @return {!Object|undefined}
+ */
+CommandLineAPIImpl.getEventListeners = function(node)
+{
+ var result = nullifyObjectProto(InjectedScriptHost.getEventListeners(node));
+ if (!result)
+ return;
+
+ // TODO(dtapuska): Remove this one closure compiler is updated
+ // to handle EventListenerOptions and passive event listeners
+ // has shipped. Don't JSDoc these otherwise it will fail.
+ // @param {boolean} capture
+ // @param {boolean} passive
+ // @return {boolean|undefined|{capture: (boolean|undefined), passive: boolean}}
+ function eventListenerOptions(capture, passive)
+ {
+ return {"capture": capture, "passive": passive};
+ }
+
+ /**
+ * @param {!Node} node
+ * @param {string} type
+ * @param {function()} listener
+ * @param {boolean} capture
+ * @param {boolean} passive
+ */
+ function removeEventListenerWrapper(node, type, listener, capture, passive)
+ {
+ node.removeEventListener(type, listener, eventListenerOptions(capture, passive));
+ }
+
+ /** @this {{type: string, listener: function(), useCapture: boolean, passive: boolean}} */
+ var removeFunc = function()
+ {
+ removeEventListenerWrapper(node, this.type, this.listener, this.useCapture, this.passive);
+ }
+ for (var type in result) {
+ var listeners = result[type];
+ for (var i = 0, listener; listener = listeners[i]; ++i) {
+ listener["type"] = type;
+ listener["remove"] = removeFunc;
+ }
+ }
+ return result;
+}
+
+/**
+ * @param {!Array.<string>|string=} types
+ * @return {!Array.<string>}
+ */
+CommandLineAPIImpl._normalizeEventTypes = function(types)
+{
+ if (typeof types === "undefined")
+ types = ["mouse", "key", "touch", "pointer", "control", "load", "unload", "abort", "error", "select", "input", "change", "submit", "reset", "focus", "blur", "resize", "scroll", "search", "devicemotion", "deviceorientation"];
+ else if (typeof types === "string")
+ types = [types];
+
+ var result = [];
+ for (var i = 0; i < types.length; ++i) {
+ if (types[i] === "mouse")
+ push(result, "click", "dblclick", "mousedown", "mouseeenter", "mouseleave", "mousemove", "mouseout", "mouseover", "mouseup", "mouseleave", "mousewheel");
+ else if (types[i] === "key")
+ push(result, "keydown", "keyup", "keypress", "textInput");
+ else if (types[i] === "touch")
+ push(result, "touchstart", "touchmove", "touchend", "touchcancel");
+ else if (types[i] === "pointer")
+ push(result, "pointerover", "pointerout", "pointerenter", "pointerleave", "pointerdown", "pointerup", "pointermove", "pointercancel", "gotpointercapture", "lostpointercapture");
+ else if (types[i] === "control")
+ push(result, "resize", "scroll", "zoom", "focus", "blur", "select", "input", "change", "submit", "reset");
+ else
+ push(result, types[i]);
+ }
+ return result;
+}
+
+/**
+ * @param {!Event} event
+ */
+CommandLineAPIImpl._logEvent = function(event)
+{
+ inspectedGlobalObject.console.log(event.type, event);
+}
+
+return injectedScript;
+})
diff --git a/deps/v8_inspector/platform/v8_inspector/InspectedContext.cpp b/deps/v8_inspector/platform/v8_inspector/InspectedContext.cpp
new file mode 100644
index 0000000000..5b52e015a5
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/InspectedContext.cpp
@@ -0,0 +1,88 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/v8_inspector/InspectedContext.h"
+
+#include "platform/v8_inspector/InjectedScript.h"
+#include "platform/v8_inspector/V8Console.h"
+#include "platform/v8_inspector/V8DebuggerImpl.h"
+#include "platform/v8_inspector/V8StringUtil.h"
+#include "platform/v8_inspector/public/V8ContextInfo.h"
+#include "platform/v8_inspector/public/V8DebuggerClient.h"
+
+namespace blink {
+
+void InspectedContext::weakCallback(const v8::WeakCallbackInfo<InspectedContext>& data)
+{
+ InspectedContext* context = data.GetParameter();
+ if (!context->m_context.IsEmpty()) {
+ context->m_context.Reset();
+ data.SetSecondPassCallback(&InspectedContext::weakCallback);
+ } else {
+ context->m_debugger->discardInspectedContext(context->m_contextGroupId, context->m_contextId);
+ }
+}
+
+void InspectedContext::consoleWeakCallback(const v8::WeakCallbackInfo<InspectedContext>& data)
+{
+ data.GetParameter()->m_console.Reset();
+}
+
+InspectedContext::InspectedContext(V8DebuggerImpl* debugger, const V8ContextInfo& info, int contextId)
+ : m_debugger(debugger)
+ , m_context(info.context->GetIsolate(), info.context)
+ , m_contextId(contextId)
+ , m_contextGroupId(info.contextGroupId)
+ , m_isDefault(info.isDefault)
+ , m_origin(info.origin)
+ , m_humanReadableName(info.humanReadableName)
+ , m_frameId(info.frameId)
+ , m_reported(false)
+{
+ m_context.SetWeak(this, &InspectedContext::weakCallback, v8::WeakCallbackType::kParameter);
+
+ v8::Isolate* isolate = m_debugger->isolate();
+ v8::Local<v8::Object> global = info.context->Global();
+ v8::Local<v8::Object> console = V8Console::createConsole(this, info.hasMemoryOnConsole);
+ if (!global->Set(info.context, toV8StringInternalized(isolate, "console"), console).FromMaybe(false))
+ return;
+ m_console.Reset(isolate, console);
+ m_console.SetWeak(this, &InspectedContext::consoleWeakCallback, v8::WeakCallbackType::kParameter);
+}
+
+InspectedContext::~InspectedContext()
+{
+ if (!m_context.IsEmpty() && !m_console.IsEmpty()) {
+ v8::HandleScope scope(isolate());
+ V8Console::clearInspectedContextIfNeeded(context(), m_console.Get(isolate()));
+ }
+}
+
+v8::Local<v8::Context> InspectedContext::context() const
+{
+ return m_context.Get(isolate());
+}
+
+v8::Isolate* InspectedContext::isolate() const
+{
+ return m_debugger->isolate();
+}
+
+void InspectedContext::createInjectedScript()
+{
+ DCHECK(!m_injectedScript);
+ v8::HandleScope handles(isolate());
+ v8::Local<v8::Context> localContext = context();
+ v8::Local<v8::Context> callingContext = isolate()->GetCallingContext();
+ if (!callingContext.IsEmpty() && !m_debugger->client()->callingContextCanAccessContext(callingContext, localContext))
+ return;
+ m_injectedScript = InjectedScript::create(this);
+}
+
+void InspectedContext::discardInjectedScript()
+{
+ m_injectedScript.reset();
+}
+
+} // namespace blink
diff --git a/deps/v8_inspector/platform/v8_inspector/InspectedContext.h b/deps/v8_inspector/platform/v8_inspector/InspectedContext.h
new file mode 100644
index 0000000000..284679ddc0
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/InspectedContext.h
@@ -0,0 +1,64 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef InspectedContext_h
+#define InspectedContext_h
+
+#include "platform/inspector_protocol/Allocator.h"
+#include "platform/inspector_protocol/Collections.h"
+#include "platform/inspector_protocol/String16.h"
+#include <v8.h>
+
+namespace blink {
+
+class InjectedScript;
+class InjectedScriptHost;
+class V8ContextInfo;
+class V8DebuggerImpl;
+
+class InspectedContext {
+ PROTOCOL_DISALLOW_COPY(InspectedContext);
+public:
+ ~InspectedContext();
+
+ v8::Local<v8::Context> context() const;
+ int contextId() const { return m_contextId; }
+ int contextGroupId() const { return m_contextGroupId; }
+ bool isDefault() const { return m_isDefault; }
+ String16 origin() const { return m_origin; }
+ String16 humanReadableName() const { return m_humanReadableName; }
+ String16 frameId() const { return m_frameId; }
+
+ bool isReported() const { return m_reported; }
+ void setReported(bool reported) { m_reported = reported; }
+
+ v8::Isolate* isolate() const;
+ V8DebuggerImpl* debugger() const { return m_debugger; }
+
+ InjectedScript* getInjectedScript() { return m_injectedScript.get(); }
+ void createInjectedScript();
+ void discardInjectedScript();
+
+private:
+ friend class V8DebuggerImpl;
+ InspectedContext(V8DebuggerImpl*, const V8ContextInfo&, int contextId);
+ static void weakCallback(const v8::WeakCallbackInfo<InspectedContext>&);
+ static void consoleWeakCallback(const v8::WeakCallbackInfo<InspectedContext>&);
+
+ V8DebuggerImpl* m_debugger;
+ v8::Global<v8::Context> m_context;
+ int m_contextId;
+ int m_contextGroupId;
+ bool m_isDefault;
+ const String16 m_origin;
+ const String16 m_humanReadableName;
+ const String16 m_frameId;
+ bool m_reported;
+ std::unique_ptr<InjectedScript> m_injectedScript;
+ v8::Global<v8::Object> m_console;
+};
+
+} // namespace blink
+
+#endif
diff --git a/deps/v8_inspector/platform/v8_inspector/InspectorWrapper.cpp b/deps/v8_inspector/platform/v8_inspector/InspectorWrapper.cpp
new file mode 100644
index 0000000000..4f5f278417
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/InspectorWrapper.cpp
@@ -0,0 +1,70 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/v8_inspector/InspectorWrapper.h"
+
+#include "platform/v8_inspector/V8Compat.h"
+#include "platform/v8_inspector/public/V8DebuggerClient.h"
+#include "wtf/Assertions.h"
+
+#include <v8-debug.h>
+
+namespace blink {
+
+v8::Local<v8::FunctionTemplate> InspectorWrapperBase::createWrapperTemplate(v8::Isolate* isolate, const char* className, const protocol::Vector<V8MethodConfiguration>& methods, const protocol::Vector<V8AttributeConfiguration>& attributes)
+{
+ v8::Local<v8::FunctionTemplate> functionTemplate = v8::FunctionTemplate::New(isolate);
+
+ functionTemplate->SetClassName(v8::String::NewFromUtf8(isolate, className, v8::NewStringType::kInternalized).ToLocalChecked());
+ v8::Local<v8::ObjectTemplate> instanceTemplate = functionTemplate->InstanceTemplate();
+
+ for (auto& config : attributes) {
+ v8::Local<v8::Name> v8name = v8::String::NewFromUtf8(isolate, config.name, v8::NewStringType::kInternalized).ToLocalChecked();
+ instanceTemplate->SetAccessor(v8name, config.callback);
+ }
+
+ for (auto& config : methods) {
+ v8::Local<v8::Name> v8name = v8::String::NewFromUtf8(isolate, config.name, v8::NewStringType::kInternalized).ToLocalChecked();
+ v8::Local<v8::FunctionTemplate> functionTemplate = v8::FunctionTemplate::New(isolate, config.callback);
+ functionTemplate->RemovePrototype();
+ instanceTemplate->Set(v8name, functionTemplate, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::DontEnum | v8::ReadOnly));
+ }
+
+ return functionTemplate;
+}
+
+v8::Local<v8::Object> InspectorWrapperBase::createWrapper(v8::Local<v8::FunctionTemplate> constructorTemplate, v8::Local<v8::Context> context)
+{
+ v8::MicrotasksScope microtasks(context->GetIsolate(), v8::MicrotasksScope::kDoNotRunMicrotasks);
+ v8::Local<v8::Function> function;
+ if (!constructorTemplate->GetFunction(context).ToLocal(&function))
+ return v8::Local<v8::Object>();
+
+ v8::Local<v8::Object> result;
+ if (!function->NewInstance(context).ToLocal(&result))
+ return v8::Local<v8::Object>();
+ return result;
+}
+
+void* InspectorWrapperBase::unwrap(v8::Local<v8::Context> context, v8::Local<v8::Object> object, const char* name)
+{
+ v8::Isolate* isolate = context->GetIsolate();
+ DCHECK(context != v8::Debug::GetDebugContext(isolate));
+
+ v8::Local<v8::Private> privateKey = v8::Private::ForApi(isolate, v8::String::NewFromUtf8(isolate, name, v8::NewStringType::kInternalized).ToLocalChecked());
+
+ v8::Local<v8::Value> value;
+ if (!object->GetPrivate(context, privateKey).ToLocal(&value))
+ return nullptr;
+ if (!value->IsExternal())
+ return nullptr;
+ return value.As<v8::External>()->Value();
+}
+
+v8::Local<v8::String> InspectorWrapperBase::v8InternalizedString(v8::Isolate* isolate, const char* name)
+{
+ return v8::String::NewFromUtf8(isolate, name, v8::NewStringType::kInternalized).ToLocalChecked();
+}
+
+} // namespace blink
diff --git a/deps/v8_inspector/platform/v8_inspector/InspectorWrapper.h b/deps/v8_inspector/platform/v8_inspector/InspectorWrapper.h
new file mode 100644
index 0000000000..e28697dbd7
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/InspectorWrapper.h
@@ -0,0 +1,88 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef InspectorWrapper_h
+#define InspectorWrapper_h
+
+#include "platform/inspector_protocol/Collections.h"
+#include <v8.h>
+
+namespace blink {
+
+class InspectorWrapperBase {
+public:
+ struct V8MethodConfiguration {
+ const char* name;
+ v8::FunctionCallback callback;
+ };
+
+ struct V8AttributeConfiguration {
+ const char* name;
+ v8::AccessorNameGetterCallback callback;
+ };
+
+ static v8::Local<v8::FunctionTemplate> createWrapperTemplate(v8::Isolate*, const char* className, const protocol::Vector<V8MethodConfiguration>& methods, const protocol::Vector<V8AttributeConfiguration>& attributes);
+
+protected:
+ static v8::Local<v8::Object> createWrapper(v8::Local<v8::FunctionTemplate>, v8::Local<v8::Context>);
+ static void* unwrap(v8::Local<v8::Context>, v8::Local<v8::Object>, const char* name);
+
+ static v8::Local<v8::String> v8InternalizedString(v8::Isolate*, const char* name);
+};
+
+template<class T, char* const hiddenPropertyName, char* const className>
+class InspectorWrapper final : public InspectorWrapperBase {
+public:
+ class WeakCallbackData final {
+ public:
+ WeakCallbackData(v8::Isolate* isolate, T* impl, v8::Local<v8::Object> wrapper)
+ : m_impl(impl)
+ , m_persistent(isolate, wrapper)
+ {
+ m_persistent.SetWeak(this, &WeakCallbackData::weakCallback, v8::WeakCallbackType::kParameter);
+ }
+
+ T* m_impl;
+ std::unique_ptr<T> m_implOwn;
+
+ private:
+ static void weakCallback(const v8::WeakCallbackInfo<WeakCallbackData>& info)
+ {
+ delete info.GetParameter();
+ }
+
+ v8::Global<v8::Object> m_persistent;
+ };
+
+ static v8::Local<v8::FunctionTemplate> createWrapperTemplate(v8::Isolate* isolate, const protocol::Vector<V8MethodConfiguration>& methods, const protocol::Vector<V8AttributeConfiguration>& attributes)
+ {
+ return InspectorWrapperBase::createWrapperTemplate(isolate, className, methods, attributes);
+ }
+
+ static v8::Local<v8::Object> wrap(v8::Local<v8::FunctionTemplate> constructorTemplate, v8::Local<v8::Context> context, T* object)
+ {
+ v8::Context::Scope contextScope(context);
+ v8::Local<v8::Object> result = InspectorWrapperBase::createWrapper(constructorTemplate, context);
+ if (result.IsEmpty())
+ return v8::Local<v8::Object>();
+ v8::Isolate* isolate = context->GetIsolate();
+ v8::Local<v8::External> objectReference = v8::External::New(isolate, new WeakCallbackData(isolate, object, result));
+
+ v8::Local<v8::Private> privateKey = v8::Private::ForApi(isolate, v8::String::NewFromUtf8(isolate, hiddenPropertyName, v8::NewStringType::kInternalized).ToLocalChecked());
+ result->SetPrivate(context, privateKey, objectReference);
+ return result;
+ }
+
+ static T* unwrap(v8::Local<v8::Context> context, v8::Local<v8::Object> object)
+ {
+ void* data = InspectorWrapperBase::unwrap(context, object, hiddenPropertyName);
+ if (!data)
+ return nullptr;
+ return reinterpret_cast<WeakCallbackData*>(data)->m_impl;
+ }
+};
+
+} // namespace blink
+
+#endif // InspectorWrapper_h
diff --git a/deps/v8_inspector/platform/v8_inspector/JavaScriptCallFrame.cpp b/deps/v8_inspector/platform/v8_inspector/JavaScriptCallFrame.cpp
new file mode 100644
index 0000000000..c72cadcafe
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/JavaScriptCallFrame.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "platform/v8_inspector/JavaScriptCallFrame.h"
+
+#include "platform/v8_inspector/V8Compat.h"
+#include "platform/v8_inspector/V8StringUtil.h"
+
+#include <v8-debug.h>
+
+namespace blink {
+
+JavaScriptCallFrame::JavaScriptCallFrame(v8::Local<v8::Context> debuggerContext, v8::Local<v8::Object> callFrame)
+ : m_isolate(debuggerContext->GetIsolate())
+ , m_debuggerContext(m_isolate, debuggerContext)
+ , m_callFrame(m_isolate, callFrame)
+{
+}
+
+JavaScriptCallFrame::~JavaScriptCallFrame()
+{
+}
+
+int JavaScriptCallFrame::callV8FunctionReturnInt(const char* name) const
+{
+ v8::HandleScope handleScope(m_isolate);
+ v8::MicrotasksScope microtasks(m_isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
+ v8::Local<v8::Context> context = v8::Local<v8::Context>::New(m_isolate, m_debuggerContext);
+ v8::Local<v8::Object> callFrame = v8::Local<v8::Object>::New(m_isolate, m_callFrame);
+ v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(callFrame->Get(toV8StringInternalized(m_isolate, name)));
+ v8::Local<v8::Value> result;
+ if (!func->Call(context, callFrame, 0, nullptr).ToLocal(&result) || !result->IsInt32())
+ return 0;
+ return result.As<v8::Int32>()->Value();
+}
+
+int JavaScriptCallFrame::sourceID() const
+{
+ return callV8FunctionReturnInt("sourceID");
+}
+
+int JavaScriptCallFrame::line() const
+{
+ return callV8FunctionReturnInt("line");
+}
+
+int JavaScriptCallFrame::column() const
+{
+ return callV8FunctionReturnInt("column");
+}
+
+int JavaScriptCallFrame::contextId() const
+{
+ return callV8FunctionReturnInt("contextId");
+}
+
+bool JavaScriptCallFrame::isAtReturn() const
+{
+ v8::HandleScope handleScope(m_isolate);
+ v8::Local<v8::Value> result = v8::Local<v8::Object>::New(m_isolate, m_callFrame)->Get(toV8StringInternalized(m_isolate, "isAtReturn"));
+ if (result.IsEmpty() || !result->IsBoolean())
+ return false;
+ return result->BooleanValue();
+}
+
+v8::Local<v8::Object> JavaScriptCallFrame::details() const
+{
+ v8::MicrotasksScope microtasks(m_isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
+ v8::Local<v8::Object> callFrame = v8::Local<v8::Object>::New(m_isolate, m_callFrame);
+ v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(callFrame->Get(toV8StringInternalized(m_isolate, "details")));
+ return v8::Local<v8::Object>::Cast(func->Call(m_isolate->GetCurrentContext(), callFrame, 0, nullptr).ToLocalChecked());
+}
+
+v8::MaybeLocal<v8::Value> JavaScriptCallFrame::evaluate(v8::Local<v8::Value> expression)
+{
+ v8::MicrotasksScope microtasks(m_isolate, v8::MicrotasksScope::kRunMicrotasks);
+ v8::Local<v8::Object> callFrame = v8::Local<v8::Object>::New(m_isolate, m_callFrame);
+ v8::Local<v8::Function> evalFunction = v8::Local<v8::Function>::Cast(callFrame->Get(toV8StringInternalized(m_isolate, "evaluate")));
+ return evalFunction->Call(m_isolate->GetCurrentContext(), callFrame, 1, &expression);
+}
+
+v8::MaybeLocal<v8::Value> JavaScriptCallFrame::restart()
+{
+ v8::MicrotasksScope microtasks(m_isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
+ v8::Local<v8::Object> callFrame = v8::Local<v8::Object>::New(m_isolate, m_callFrame);
+ v8::Local<v8::Function> restartFunction = v8::Local<v8::Function>::Cast(callFrame->Get(toV8StringInternalized(m_isolate, "restart")));
+ v8::Debug::SetLiveEditEnabled(m_isolate, true);
+ v8::MaybeLocal<v8::Value> result = restartFunction->Call(m_isolate->GetCurrentContext(), callFrame, 0, nullptr);
+ v8::Debug::SetLiveEditEnabled(m_isolate, false);
+ return result;
+}
+
+v8::MaybeLocal<v8::Value> JavaScriptCallFrame::setVariableValue(int scopeNumber, v8::Local<v8::Value> variableName, v8::Local<v8::Value> newValue)
+{
+ v8::MicrotasksScope microtasks(m_isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
+ v8::Local<v8::Object> callFrame = v8::Local<v8::Object>::New(m_isolate, m_callFrame);
+ v8::Local<v8::Function> setVariableValueFunction = v8::Local<v8::Function>::Cast(callFrame->Get(toV8StringInternalized(m_isolate, "setVariableValue")));
+ v8::Local<v8::Value> argv[] = {
+ v8::Local<v8::Value>(v8::Integer::New(m_isolate, scopeNumber)),
+ variableName,
+ newValue
+ };
+ return setVariableValueFunction->Call(m_isolate->GetCurrentContext(), callFrame, PROTOCOL_ARRAY_LENGTH(argv), argv);
+}
+
+} // namespace blink
diff --git a/deps/v8_inspector/platform/v8_inspector/JavaScriptCallFrame.h b/deps/v8_inspector/platform/v8_inspector/JavaScriptCallFrame.h
new file mode 100644
index 0000000000..e34d1d03ec
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/JavaScriptCallFrame.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JavaScriptCallFrame_h
+#define JavaScriptCallFrame_h
+
+#include "platform/inspector_protocol/Collections.h"
+#include "platform/inspector_protocol/String16.h"
+#include "wtf/PtrUtil.h"
+#include "wtf/PtrUtil.h"
+#include <v8.h>
+
+namespace blink {
+
+class JavaScriptCallFrame {
+public:
+ static std::unique_ptr<JavaScriptCallFrame> create(v8::Local<v8::Context> debuggerContext, v8::Local<v8::Object> callFrame)
+ {
+ return wrapUnique(new JavaScriptCallFrame(debuggerContext, callFrame));
+ }
+ ~JavaScriptCallFrame();
+
+ int sourceID() const;
+ int line() const;
+ int column() const;
+ int contextId() const;
+
+ bool isAtReturn() const;
+ v8::Local<v8::Object> details() const;
+
+ v8::MaybeLocal<v8::Value> evaluate(v8::Local<v8::Value> expression);
+ v8::MaybeLocal<v8::Value> restart();
+ v8::MaybeLocal<v8::Value> setVariableValue(int scopeNumber, v8::Local<v8::Value> variableName, v8::Local<v8::Value> newValue);
+private:
+ JavaScriptCallFrame(v8::Local<v8::Context> debuggerContext, v8::Local<v8::Object> callFrame);
+
+ int callV8FunctionReturnInt(const char* name) const;
+
+ v8::Isolate* m_isolate;
+ v8::Global<v8::Context> m_debuggerContext;
+ v8::Global<v8::Object> m_callFrame;
+};
+
+using JavaScriptCallFrames = protocol::Vector<std::unique_ptr<JavaScriptCallFrame>>;
+
+} // namespace blink
+
+#endif // JavaScriptCallFrame_h
diff --git a/deps/v8_inspector/platform/v8_inspector/OWNERS b/deps/v8_inspector/platform/v8_inspector/OWNERS
new file mode 100644
index 0000000000..c34ad775ca
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/OWNERS
@@ -0,0 +1,5 @@
+alph@chromium.org
+caseq@chromium.org
+dgozman@chromium.org
+kozyatinskiy@chromium.org
+pfeldman@chromium.org
diff --git a/deps/v8_inspector/platform/v8_inspector/RemoteObjectId.cpp b/deps/v8_inspector/platform/v8_inspector/RemoteObjectId.cpp
new file mode 100644
index 0000000000..1f0332b44f
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/RemoteObjectId.cpp
@@ -0,0 +1,72 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/v8_inspector/RemoteObjectId.h"
+
+#include "platform/inspector_protocol/Parser.h"
+#include "platform/inspector_protocol/Values.h"
+#include "wtf/PtrUtil.h"
+
+namespace blink {
+
+RemoteObjectIdBase::RemoteObjectIdBase() : m_injectedScriptId(0) { }
+
+std::unique_ptr<protocol::DictionaryValue> RemoteObjectIdBase::parseInjectedScriptId(const String16& objectId)
+{
+ std::unique_ptr<protocol::Value> parsedValue = protocol::parseJSON(objectId);
+ if (!parsedValue || parsedValue->type() != protocol::Value::TypeObject)
+ return nullptr;
+
+ std::unique_ptr<protocol::DictionaryValue> parsedObjectId(protocol::DictionaryValue::cast(parsedValue.release()));
+ bool success = parsedObjectId->getNumber("injectedScriptId", &m_injectedScriptId);
+ if (success)
+ return parsedObjectId;
+ return nullptr;
+}
+
+RemoteObjectId::RemoteObjectId() : RemoteObjectIdBase(), m_id(0) { }
+
+std::unique_ptr<RemoteObjectId> RemoteObjectId::parse(ErrorString* errorString, const String16& objectId)
+{
+ std::unique_ptr<RemoteObjectId> result(new RemoteObjectId());
+ std::unique_ptr<protocol::DictionaryValue> parsedObjectId = result->parseInjectedScriptId(objectId);
+ if (!parsedObjectId) {
+ *errorString = "Invalid remote object id";
+ return nullptr;
+ }
+
+ bool success = parsedObjectId->getNumber("id", &result->m_id);
+ if (!success) {
+ *errorString = "Invalid remote object id";
+ return nullptr;
+ }
+ return result;
+}
+
+RemoteCallFrameId::RemoteCallFrameId() : RemoteObjectIdBase(), m_frameOrdinal(0) { }
+
+std::unique_ptr<RemoteCallFrameId> RemoteCallFrameId::parse(ErrorString* errorString, const String16& objectId)
+{
+ std::unique_ptr<RemoteCallFrameId> result(new RemoteCallFrameId());
+ std::unique_ptr<protocol::DictionaryValue> parsedObjectId = result->parseInjectedScriptId(objectId);
+ if (!parsedObjectId) {
+ *errorString = "Invalid call frame id";
+ return nullptr;
+ }
+
+ bool success = parsedObjectId->getNumber("ordinal", &result->m_frameOrdinal);
+ if (!success) {
+ *errorString = "Invalid call frame id";
+ return nullptr;
+ }
+
+ return result;
+}
+
+String16 RemoteCallFrameId::serialize(int injectedScriptId, int frameOrdinal)
+{
+ return "{\"ordinal\":" + String16::number(frameOrdinal) + ",\"injectedScriptId\":" + String16::number(injectedScriptId) + "}";
+}
+
+} // namespace blink
diff --git a/deps/v8_inspector/platform/v8_inspector/RemoteObjectId.h b/deps/v8_inspector/platform/v8_inspector/RemoteObjectId.h
new file mode 100644
index 0000000000..ae1cf47ca4
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/RemoteObjectId.h
@@ -0,0 +1,59 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef RemoteObjectId_h
+#define RemoteObjectId_h
+
+#include "platform/inspector_protocol/String16.h"
+#include "platform/inspector_protocol/TypeBuilder.h"
+#include "wtf/PtrUtil.h"
+
+namespace blink {
+
+namespace protocol {
+class DictionaryValue;
+}
+
+class RemoteObjectIdBase {
+public:
+ int contextId() const { return m_injectedScriptId; }
+
+protected:
+ RemoteObjectIdBase();
+ ~RemoteObjectIdBase() { }
+
+ std::unique_ptr<protocol::DictionaryValue> parseInjectedScriptId(const String16&);
+
+ int m_injectedScriptId;
+};
+
+class RemoteObjectId final : public RemoteObjectIdBase {
+public:
+ static std::unique_ptr<RemoteObjectId> parse(ErrorString*, const String16&);
+ ~RemoteObjectId() { }
+ int id() const { return m_id; }
+
+private:
+ RemoteObjectId();
+
+ int m_id;
+};
+
+class RemoteCallFrameId final : public RemoteObjectIdBase {
+public:
+ static std::unique_ptr<RemoteCallFrameId> parse(ErrorString*, const String16&);
+ ~RemoteCallFrameId() { }
+
+ int frameOrdinal() const { return m_frameOrdinal; }
+
+ static String16 serialize(int injectedScriptId, int frameOrdinal);
+private:
+ RemoteCallFrameId();
+
+ int m_frameOrdinal;
+};
+
+} // namespace blink
+
+#endif // !defined(RemoteObjectId_h)
diff --git a/deps/v8_inspector/platform/v8_inspector/ScriptBreakpoint.h b/deps/v8_inspector/platform/v8_inspector/ScriptBreakpoint.h
new file mode 100644
index 0000000000..6b2db21498
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/ScriptBreakpoint.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ScriptBreakpoint_h
+#define ScriptBreakpoint_h
+
+#include "platform/inspector_protocol/Allocator.h"
+#include "platform/inspector_protocol/String16.h"
+
+namespace blink {
+
+struct ScriptBreakpoint {
+ ScriptBreakpoint() : ScriptBreakpoint(0, 0, String16()) { }
+
+ ScriptBreakpoint(int lineNumber, int columnNumber, const String16& condition)
+ : lineNumber(lineNumber)
+ , columnNumber(columnNumber)
+ , condition(condition)
+ {
+ }
+
+ int lineNumber;
+ int columnNumber;
+ String16 condition;
+};
+
+} // namespace blink
+
+#endif // !defined(ScriptBreakpoint_h)
diff --git a/deps/v8_inspector/platform/v8_inspector/V8Compat.h b/deps/v8_inspector/platform/v8_inspector/V8Compat.h
new file mode 100644
index 0000000000..17d104f773
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8Compat.h
@@ -0,0 +1,28 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8Compat_h
+#define V8Compat_h
+
+#include <v8.h>
+
+#if V8_MAJOR_VERSION < 5 || (V8_MAJOR_VERSION == 5 && V8_MINOR_VERSION < 2)
+namespace v8 {
+
+// In standalone V8 inspector this is expected to be noop anyways...
+class V8_EXPORT MicrotasksScope {
+public:
+ enum Type { kRunMicrotasks, kDoNotRunMicrotasks };
+
+ MicrotasksScope(Isolate* isolate, Type type)
+ {
+ // No-op
+ }
+};
+
+} // namespace v8
+
+#endif // V8_MAJOR_VERSION < 5 || (V8_MAJOR_VERSION == 5 && V8_MINOR_VERSION < 2)
+
+#endif // V8Compat_h
diff --git a/deps/v8_inspector/platform/v8_inspector/V8Console.cpp b/deps/v8_inspector/platform/v8_inspector/V8Console.cpp
new file mode 100644
index 0000000000..f3f7fe171e
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8Console.cpp
@@ -0,0 +1,730 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/v8_inspector/V8Console.h"
+
+#include "platform/inspector_protocol/String16.h"
+#include "platform/v8_inspector/InjectedScript.h"
+#include "platform/v8_inspector/InspectedContext.h"
+#include "platform/v8_inspector/V8Compat.h"
+#include "platform/v8_inspector/V8DebuggerAgentImpl.h"
+#include "platform/v8_inspector/V8DebuggerImpl.h"
+#include "platform/v8_inspector/V8InspectorSessionImpl.h"
+#include "platform/v8_inspector/V8ProfilerAgentImpl.h"
+#include "platform/v8_inspector/V8RuntimeAgentImpl.h"
+#include "platform/v8_inspector/V8StackTraceImpl.h"
+#include "platform/v8_inspector/V8StringUtil.h"
+#include "platform/v8_inspector/public/ConsoleAPITypes.h"
+#include "platform/v8_inspector/public/ConsoleTypes.h"
+#include "platform/v8_inspector/public/V8DebuggerClient.h"
+
+namespace blink {
+
+namespace {
+
+v8::Local<v8::Private> inspectedContextPrivateKey(v8::Isolate* isolate)
+{
+ return v8::Private::ForApi(isolate, toV8StringInternalized(isolate, "V8Console#InspectedContext"));
+}
+
+class ConsoleHelper {
+ PROTOCOL_DISALLOW_COPY(ConsoleHelper);
+public:
+ ConsoleHelper(const v8::FunctionCallbackInfo<v8::Value>& info)
+ : m_info(info)
+ , m_isolate(info.GetIsolate())
+ , m_context(info.GetIsolate()->GetCurrentContext())
+ , m_inspectedContext(nullptr)
+ , m_debuggerClient(nullptr)
+ {
+ }
+
+ v8::Local<v8::Object> ensureConsole()
+ {
+ if (m_console.IsEmpty()) {
+ DCHECK(!m_info.Data().IsEmpty());
+ DCHECK(!m_info.Data()->IsUndefined());
+ m_console = m_info.Data().As<v8::Object>();
+ }
+ return m_console;
+ }
+
+ InspectedContext* ensureInspectedContext()
+ {
+ if (m_inspectedContext)
+ return m_inspectedContext;
+ v8::Local<v8::Object> console = ensureConsole();
+
+ v8::Local<v8::Private> key = inspectedContextPrivateKey(m_isolate);
+ v8::Local<v8::Value> inspectedContextValue;
+ if (!console->GetPrivate(m_context, key).ToLocal(&inspectedContextValue))
+ return nullptr;
+ DCHECK(inspectedContextValue->IsExternal());
+ m_inspectedContext = static_cast<InspectedContext*>(inspectedContextValue.As<v8::External>()->Value());
+ return m_inspectedContext;
+ }
+
+ V8DebuggerClient* ensureDebuggerClient()
+ {
+ if (m_debuggerClient)
+ return m_debuggerClient;
+ InspectedContext* inspectedContext = ensureInspectedContext();
+ if (!inspectedContext)
+ return nullptr;
+ m_debuggerClient = inspectedContext->debugger()->client();
+ return m_debuggerClient;
+ }
+
+ void addMessage(MessageType type, MessageLevel level, bool allowEmptyArguments, int skipArgumentCount)
+ {
+ if (!allowEmptyArguments && !m_info.Length())
+ return;
+ if (V8DebuggerClient* debuggerClient = ensureDebuggerClient())
+ debuggerClient->reportMessageToConsole(m_context, type, level, String16(), &m_info, skipArgumentCount, -1);
+ }
+
+ void addMessage(MessageType type, MessageLevel level, const String16& message)
+ {
+ if (V8DebuggerClient* debuggerClient = ensureDebuggerClient())
+ debuggerClient->reportMessageToConsole(m_context, type, level, message, nullptr, 0 /* skipArgumentsCount */, 1 /* maxStackSize */);
+ }
+
+ void addDeprecationMessage(const char* id, const String16& message)
+ {
+ if (checkAndSetPrivateFlagOnConsole(id, false))
+ return;
+ if (V8DebuggerClient* debuggerClient = ensureDebuggerClient())
+ debuggerClient->reportMessageToConsole(m_context, LogMessageType, WarningMessageLevel, message, nullptr, 0 /* skipArgumentsCount */, 0 /* maxStackSize */);
+ }
+
+ bool firstArgToBoolean(bool defaultValue)
+ {
+ if (m_info.Length() < 1)
+ return defaultValue;
+ if (m_info[0]->IsBoolean())
+ return m_info[0].As<v8::Boolean>()->Value();
+ return m_info[0]->BooleanValue(m_context).FromMaybe(defaultValue);
+ }
+
+ String16 firstArgToString(const String16& defaultValue)
+ {
+ if (m_info.Length() < 1)
+ return defaultValue;
+ v8::Local<v8::String> titleValue;
+ if (m_info[0]->IsObject()) {
+ if (!m_info[0].As<v8::Object>()->ObjectProtoToString(m_context).ToLocal(&titleValue))
+ return defaultValue;
+ } else {
+ if (!m_info[0]->ToString(m_context).ToLocal(&titleValue))
+ return defaultValue;
+ }
+ return toProtocolString(titleValue);
+ }
+
+ v8::MaybeLocal<v8::Object> firstArgAsObject()
+ {
+ if (m_info.Length() < 1 || !m_info[0]->IsObject())
+ return v8::MaybeLocal<v8::Object>();
+ return m_info[0].As<v8::Object>();
+ }
+
+ v8::MaybeLocal<v8::Function> firstArgAsFunction()
+ {
+ if (m_info.Length() < 1 || !m_info[0]->IsFunction())
+ return v8::MaybeLocal<v8::Function>();
+ return m_info[0].As<v8::Function>();
+ }
+
+ v8::MaybeLocal<v8::Map> privateMap(const char* name)
+ {
+ v8::Local<v8::Object> console = ensureConsole();
+ v8::Local<v8::Private> privateKey = v8::Private::ForApi(m_isolate, toV8StringInternalized(m_isolate, name));
+ v8::Local<v8::Value> mapValue;
+ if (!console->GetPrivate(m_context, privateKey).ToLocal(&mapValue))
+ return v8::MaybeLocal<v8::Map>();
+ if (mapValue->IsUndefined()) {
+ v8::Local<v8::Map> map = v8::Map::New(m_isolate);
+ if (!console->SetPrivate(m_context, privateKey, map).FromMaybe(false))
+ return v8::MaybeLocal<v8::Map>();
+ return map;
+ }
+ return mapValue->IsMap() ? mapValue.As<v8::Map>() : v8::MaybeLocal<v8::Map>();
+ }
+
+ int64_t getIntFromMap(v8::Local<v8::Map> map, const String16& key, int64_t defaultValue)
+ {
+ v8::Local<v8::String> v8Key = toV8String(m_isolate, key);
+ if (!map->Has(m_context, v8Key).FromMaybe(false))
+ return defaultValue;
+ v8::Local<v8::Value> intValue;
+ if (!map->Get(m_context, v8Key).ToLocal(&intValue))
+ return defaultValue;
+ return intValue.As<v8::Integer>()->Value();
+ }
+
+ void setIntOnMap(v8::Local<v8::Map> map, const String16& key, int64_t value)
+ {
+ v8::Local<v8::String> v8Key = toV8String(m_isolate, key);
+ if (!map->Set(m_context, v8Key, v8::Integer::New(m_isolate, value)).ToLocal(&map))
+ return;
+ }
+
+ double getDoubleFromMap(v8::Local<v8::Map> map, const String16& key, double defaultValue)
+ {
+ v8::Local<v8::String> v8Key = toV8String(m_isolate, key);
+ if (!map->Has(m_context, v8Key).FromMaybe(false))
+ return defaultValue;
+ v8::Local<v8::Value> intValue;
+ if (!map->Get(m_context, v8Key).ToLocal(&intValue))
+ return defaultValue;
+ return intValue.As<v8::Number>()->Value();
+ }
+
+ void setDoubleOnMap(v8::Local<v8::Map> map, const String16& key, double value)
+ {
+ v8::Local<v8::String> v8Key = toV8String(m_isolate, key);
+ if (!map->Set(m_context, v8Key, v8::Number::New(m_isolate, value)).ToLocal(&map))
+ return;
+ }
+
+ V8ProfilerAgentImpl* profilerAgent()
+ {
+ if (V8InspectorSessionImpl* session = currentSession()) {
+ if (session && session->profilerAgentImpl()->enabled())
+ return session->profilerAgentImpl();
+ }
+ return nullptr;
+ }
+
+ V8DebuggerAgentImpl* debuggerAgent()
+ {
+ if (V8InspectorSessionImpl* session = currentSession()) {
+ if (session && session->debuggerAgentImpl()->enabled())
+ return session->debuggerAgentImpl();
+ }
+ return nullptr;
+ }
+
+ V8InspectorSessionImpl* currentSession()
+ {
+ InspectedContext* inspectedContext = ensureInspectedContext();
+ if (!inspectedContext)
+ return nullptr;
+ return inspectedContext->debugger()->sessionForContextGroup(inspectedContext->contextGroupId());
+ }
+
+private:
+ const v8::FunctionCallbackInfo<v8::Value>& m_info;
+ v8::Isolate* m_isolate;
+ v8::Local<v8::Context> m_context;
+ v8::Local<v8::Object> m_console;
+ InspectedContext* m_inspectedContext;
+ V8DebuggerClient* m_debuggerClient;
+
+ bool checkAndSetPrivateFlagOnConsole(const char* name, bool defaultValue)
+ {
+ v8::Local<v8::Object> console = ensureConsole();
+ v8::Local<v8::Private> key = v8::Private::ForApi(m_isolate, toV8StringInternalized(m_isolate, name));
+ v8::Local<v8::Value> flagValue;
+ if (!console->GetPrivate(m_context, key).ToLocal(&flagValue))
+ return defaultValue;
+ DCHECK(flagValue->IsUndefined() || flagValue->IsBoolean());
+ if (flagValue->IsBoolean()) {
+ DCHECK(flagValue.As<v8::Boolean>()->Value());
+ return true;
+ }
+ if (!console->SetPrivate(m_context, key, v8::True(m_isolate)).FromMaybe(false))
+ return defaultValue;
+ return false;
+ }
+};
+
+void returnDataCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ info.GetReturnValue().Set(info.Data());
+}
+
+void createBoundFunctionProperty(v8::Local<v8::Context> context, v8::Local<v8::Object> console, const char* name, v8::FunctionCallback callback, const char* description = nullptr)
+{
+ v8::Local<v8::String> funcName = toV8StringInternalized(context->GetIsolate(), name);
+ v8::Local<v8::Function> func;
+ if (!v8::Function::New(context, callback, console).ToLocal(&func))
+ return;
+ func->SetName(funcName);
+ if (description) {
+ v8::Local<v8::String> returnValue = toV8String(context->GetIsolate(), description);
+ v8::Local<v8::Function> toStringFunction;
+ if (v8::Function::New(context, returnDataCallback, returnValue).ToLocal(&toStringFunction))
+ func->Set(toV8StringInternalized(context->GetIsolate(), "toString"), toStringFunction);
+ }
+ if (!console->Set(context, funcName, func).FromMaybe(false))
+ return;
+}
+
+} // namespace
+
+void V8Console::debugCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper(info).addMessage(LogMessageType, DebugMessageLevel, false, 0);
+}
+
+void V8Console::errorCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper(info).addMessage(LogMessageType, ErrorMessageLevel, false, 0);
+}
+
+void V8Console::infoCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper(info).addMessage(LogMessageType, InfoMessageLevel, false, 0);
+}
+
+void V8Console::logCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper(info).addMessage(LogMessageType, LogMessageLevel, false, 0);
+}
+
+void V8Console::warnCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper(info).addMessage(LogMessageType, WarningMessageLevel, false, 0);
+}
+
+void V8Console::dirCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper(info).addMessage(DirMessageType, LogMessageLevel, false, 0);
+}
+
+void V8Console::dirxmlCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper(info).addMessage(DirXMLMessageType, LogMessageLevel, false, 0);
+}
+
+void V8Console::tableCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper(info).addMessage(TableMessageType, LogMessageLevel, false, 0);
+}
+
+void V8Console::traceCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper(info).addMessage(TraceMessageType, LogMessageLevel, true, 0);
+}
+
+void V8Console::groupCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper(info).addMessage(StartGroupMessageType, LogMessageLevel, true, 0);
+}
+
+void V8Console::groupCollapsedCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper(info).addMessage(StartGroupCollapsedMessageType, LogMessageLevel, true, 0);
+}
+
+void V8Console::groupEndCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper(info).addMessage(EndGroupMessageType, LogMessageLevel, true, 0);
+}
+
+void V8Console::clearCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper(info).addMessage(ClearMessageType, LogMessageLevel, true, 0);
+}
+
+void V8Console::countCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper helper(info);
+
+ String16 title = helper.firstArgToString(String16());
+ String16 identifier;
+ if (title.isEmpty()) {
+ std::unique_ptr<V8StackTraceImpl> stackTrace = V8StackTraceImpl::capture(nullptr, 1);
+ if (stackTrace)
+ identifier = stackTrace->topSourceURL() + ":" + String16::number(stackTrace->topLineNumber());
+ } else {
+ identifier = title + "@";
+ }
+
+ v8::Local<v8::Map> countMap;
+ if (!helper.privateMap("V8Console#countMap").ToLocal(&countMap))
+ return;
+ int64_t count = helper.getIntFromMap(countMap, identifier, 0) + 1;
+ helper.setIntOnMap(countMap, identifier, count);
+ helper.addMessage(CountMessageType, DebugMessageLevel, title + ": " + String16::number(count));
+}
+
+void V8Console::assertCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper helper(info);
+ if (helper.firstArgToBoolean(false))
+ return;
+ helper.addMessage(AssertMessageType, ErrorMessageLevel, true, 1);
+ if (V8DebuggerAgentImpl* debuggerAgent = helper.debuggerAgent())
+ debuggerAgent->breakProgramOnException(protocol::Debugger::Paused::ReasonEnum::Assert, nullptr);
+}
+
+void V8Console::markTimelineCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper(info).addDeprecationMessage("V8Console#markTimelineDeprecated", "'console.markTimeline' is deprecated. Please use 'console.timeStamp' instead.");
+ timeStampCallback(info);
+}
+
+void V8Console::profileCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper helper(info);
+ if (V8ProfilerAgentImpl* profilerAgent = helper.profilerAgent())
+ profilerAgent->consoleProfile(helper.firstArgToString(String16()));
+}
+
+void V8Console::profileEndCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper helper(info);
+ if (V8ProfilerAgentImpl* profilerAgent = helper.profilerAgent())
+ profilerAgent->consoleProfileEnd(helper.firstArgToString(String16()));
+}
+
+static void timeFunction(const v8::FunctionCallbackInfo<v8::Value>& info, bool timelinePrefix)
+{
+ ConsoleHelper helper(info);
+ if (V8DebuggerClient* client = helper.ensureDebuggerClient()) {
+ String16 protocolTitle = helper.firstArgToString("default");
+ if (timelinePrefix)
+ protocolTitle = "Timeline '" + protocolTitle + "'";
+ client->consoleTime(protocolTitle);
+
+ v8::Local<v8::Map> timeMap;
+ if (!helper.privateMap("V8Console#timeMap").ToLocal(&timeMap))
+ return;
+ helper.setDoubleOnMap(timeMap, protocolTitle, client->currentTimeMS());
+ }
+}
+
+static void timeEndFunction(const v8::FunctionCallbackInfo<v8::Value>& info, bool timelinePrefix)
+{
+ ConsoleHelper helper(info);
+ if (V8DebuggerClient* client = helper.ensureDebuggerClient()) {
+ String16 protocolTitle = helper.firstArgToString("default");
+ if (timelinePrefix)
+ protocolTitle = "Timeline '" + protocolTitle + "'";
+ client->consoleTimeEnd(protocolTitle);
+
+ v8::Local<v8::Map> timeMap;
+ if (!helper.privateMap("V8Console#timeMap").ToLocal(&timeMap))
+ return;
+ double elapsed = client->currentTimeMS() - helper.getDoubleFromMap(timeMap, protocolTitle, 0.0);
+ String16 message = protocolTitle + ": " + String16::fromDoubleFixedPrecision(elapsed, 3) + "ms";
+ helper.addMessage(TimeEndMessageType, DebugMessageLevel, message);
+ }
+}
+
+void V8Console::timelineCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper(info).addDeprecationMessage("V8Console#timeline", "'console.timeline' is deprecated. Please use 'console.time' instead.");
+ timeFunction(info, true);
+}
+
+void V8Console::timelineEndCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper(info).addDeprecationMessage("V8Console#timelineEnd", "'console.timelineEnd' is deprecated. Please use 'console.timeEnd' instead.");
+ timeEndFunction(info, true);
+}
+
+void V8Console::timeCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ timeFunction(info, false);
+}
+
+void V8Console::timeEndCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ timeEndFunction(info, false);
+}
+
+void V8Console::timeStampCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper helper(info);
+ if (V8DebuggerClient* client = helper.ensureDebuggerClient())
+ client->consoleTimeStamp(helper.firstArgToString(String16()));
+}
+
+void V8Console::memoryGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ if (V8DebuggerClient* client = ConsoleHelper(info).ensureDebuggerClient()) {
+ v8::Local<v8::Value> memoryValue;
+ if (!client->memoryInfo(info.GetIsolate(), info.GetIsolate()->GetCurrentContext(), info.Holder()).ToLocal(&memoryValue))
+ return;
+ info.GetReturnValue().Set(memoryValue);
+ }
+}
+
+void V8Console::memorySetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ // We can't make the attribute readonly as it breaks existing code that relies on being able to assign to console.memory in strict mode. Instead, the setter just ignores the passed value. http://crbug.com/468611
+}
+
+void V8Console::keysCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ v8::Isolate* isolate = info.GetIsolate();
+ info.GetReturnValue().Set(v8::Array::New(isolate));
+
+ ConsoleHelper helper(info);
+ v8::Local<v8::Object> obj;
+ if (!helper.firstArgAsObject().ToLocal(&obj))
+ return;
+ v8::Local<v8::Array> names;
+ if (!obj->GetOwnPropertyNames(isolate->GetCurrentContext()).ToLocal(&names))
+ return;
+ info.GetReturnValue().Set(names);
+}
+
+void V8Console::valuesCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ v8::Isolate* isolate = info.GetIsolate();
+ info.GetReturnValue().Set(v8::Array::New(isolate));
+
+ ConsoleHelper helper(info);
+ v8::Local<v8::Object> obj;
+ if (!helper.firstArgAsObject().ToLocal(&obj))
+ return;
+ v8::Local<v8::Array> names;
+ v8::Local<v8::Context> context = isolate->GetCurrentContext();
+ if (!obj->GetOwnPropertyNames(context).ToLocal(&names))
+ return;
+ v8::Local<v8::Array> values = v8::Array::New(isolate, names->Length());
+ for (size_t i = 0; i < names->Length(); ++i) {
+ v8::Local<v8::Value> key;
+ if (!names->Get(context, i).ToLocal(&key))
+ continue;
+ v8::Local<v8::Value> value;
+ if (!obj->Get(context, key).ToLocal(&value))
+ continue;
+ if (!values->Set(context, i, value).FromMaybe(false))
+ continue;
+ }
+ info.GetReturnValue().Set(values);
+}
+
+static void setFunctionBreakpoint(ConsoleHelper& helper, v8::Local<v8::Function> function, V8DebuggerAgentImpl::BreakpointSource source, const String16& condition, bool enable)
+{
+ V8DebuggerAgentImpl* debuggerAgent = helper.debuggerAgent();
+ if (!debuggerAgent)
+ return;
+ String16 scriptId = String16::number(function->ScriptId());
+ int lineNumber = function->GetScriptLineNumber();
+ int columnNumber = function->GetScriptColumnNumber();
+ if (lineNumber == v8::Function::kLineOffsetNotFound || columnNumber == v8::Function::kLineOffsetNotFound)
+ return;
+ if (enable)
+ debuggerAgent->setBreakpointAt(scriptId, lineNumber, columnNumber, source, condition);
+ else
+ debuggerAgent->removeBreakpointAt(scriptId, lineNumber, columnNumber, source);
+}
+
+void V8Console::debugFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper helper(info);
+ v8::Local<v8::Function> function;
+ if (!helper.firstArgAsFunction().ToLocal(&function))
+ return;
+ setFunctionBreakpoint(helper, function, V8DebuggerAgentImpl::DebugCommandBreakpointSource, String16(), true);
+}
+
+void V8Console::undebugFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper helper(info);
+ v8::Local<v8::Function> function;
+ if (!helper.firstArgAsFunction().ToLocal(&function))
+ return;
+ setFunctionBreakpoint(helper, function, V8DebuggerAgentImpl::DebugCommandBreakpointSource, String16(), false);
+}
+
+void V8Console::monitorFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper helper(info);
+ v8::Local<v8::Function> function;
+ if (!helper.firstArgAsFunction().ToLocal(&function))
+ return;
+ v8::Local<v8::Value> name = function->GetName();
+ if (!name->IsString() || !v8::Local<v8::String>::Cast(name)->Length())
+ name = function->GetInferredName();
+ String16 functionName = toProtocolStringWithTypeCheck(name);
+ String16Builder builder;
+ builder.append("console.log(\"function ");
+ if (functionName.isEmpty())
+ builder.append("(anonymous function)");
+ else
+ builder.append(functionName);
+ builder.append(" called\" + (arguments.length > 0 ? \" with arguments: \" + Array.prototype.join.call(arguments, \", \") : \"\")) && false");
+ setFunctionBreakpoint(helper, function, V8DebuggerAgentImpl::MonitorCommandBreakpointSource, builder.toString(), true);
+}
+
+void V8Console::unmonitorFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper helper(info);
+ v8::Local<v8::Function> function;
+ if (!helper.firstArgAsFunction().ToLocal(&function))
+ return;
+ setFunctionBreakpoint(helper, function, V8DebuggerAgentImpl::MonitorCommandBreakpointSource, String16(), false);
+}
+
+void V8Console::lastEvaluationResultCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ ConsoleHelper helper(info);
+ InspectedContext* context = helper.ensureInspectedContext();
+ if (!context)
+ return;
+ if (InjectedScript* injectedScript = context->getInjectedScript())
+ info.GetReturnValue().Set(injectedScript->lastEvaluationResult());
+}
+
+static void inspectImpl(const v8::FunctionCallbackInfo<v8::Value>& info, bool copyToClipboard)
+{
+ if (info.Length() < 1)
+ return;
+ if (!copyToClipboard)
+ info.GetReturnValue().Set(info[0]);
+
+ ConsoleHelper helper(info);
+ InspectedContext* context = helper.ensureInspectedContext();
+ if (!context)
+ return;
+ InjectedScript* injectedScript = context->getInjectedScript();
+ if (!injectedScript)
+ return;
+ ErrorString errorString;
+ std::unique_ptr<protocol::Runtime::RemoteObject> wrappedObject = injectedScript->wrapObject(&errorString, info[0], "", false /** forceValueType */, false /** generatePreview */);
+ if (!wrappedObject || !errorString.isEmpty())
+ return;
+
+ std::unique_ptr<protocol::DictionaryValue> hints = protocol::DictionaryValue::create();
+ if (copyToClipboard)
+ hints->setBoolean("copyToClipboard", true);
+ if (V8InspectorSessionImpl* session = helper.currentSession())
+ session->runtimeAgentImpl()->inspect(std::move(wrappedObject), std::move(hints));
+}
+
+void V8Console::inspectCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ inspectImpl(info, false);
+}
+
+void V8Console::copyCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ inspectImpl(info, true);
+}
+
+void V8Console::inspectedObject(const v8::FunctionCallbackInfo<v8::Value>& info, unsigned num)
+{
+ DCHECK(num < V8InspectorSessionImpl::kInspectedObjectBufferSize);
+ ConsoleHelper helper(info);
+ if (V8InspectorSessionImpl* session = helper.currentSession()) {
+ V8InspectorSession::Inspectable* object = session->inspectedObject(num);
+ v8::Isolate* isolate = info.GetIsolate();
+ if (object)
+ info.GetReturnValue().Set(object->get(isolate->GetCurrentContext()));
+ else
+ info.GetReturnValue().Set(v8::Undefined(isolate));
+ }
+}
+
+v8::Local<v8::Object> V8Console::createConsole(InspectedContext* inspectedContext, bool hasMemoryAttribute)
+{
+ v8::Local<v8::Context> context = inspectedContext->context();
+ v8::Isolate* isolate = context->GetIsolate();
+ v8::MicrotasksScope microtasksScope(isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
+
+ v8::Local<v8::Object> console = v8::Object::New(isolate);
+
+ createBoundFunctionProperty(context, console, "debug", V8Console::debugCallback);
+ createBoundFunctionProperty(context, console, "error", V8Console::errorCallback);
+ createBoundFunctionProperty(context, console, "info", V8Console::infoCallback);
+ createBoundFunctionProperty(context, console, "log", V8Console::logCallback);
+ createBoundFunctionProperty(context, console, "warn", V8Console::warnCallback);
+ createBoundFunctionProperty(context, console, "dir", V8Console::dirCallback);
+ createBoundFunctionProperty(context, console, "dirxml", V8Console::dirxmlCallback);
+ createBoundFunctionProperty(context, console, "table", V8Console::tableCallback);
+ createBoundFunctionProperty(context, console, "trace", V8Console::traceCallback);
+ createBoundFunctionProperty(context, console, "group", V8Console::groupCallback);
+ createBoundFunctionProperty(context, console, "groupCollapsed", V8Console::groupCollapsedCallback);
+ createBoundFunctionProperty(context, console, "groupEnd", V8Console::groupEndCallback);
+ createBoundFunctionProperty(context, console, "clear", V8Console::clearCallback);
+ createBoundFunctionProperty(context, console, "count", V8Console::countCallback);
+ createBoundFunctionProperty(context, console, "assert", V8Console::assertCallback);
+ createBoundFunctionProperty(context, console, "markTimeline", V8Console::markTimelineCallback);
+ createBoundFunctionProperty(context, console, "profile", V8Console::profileCallback);
+ createBoundFunctionProperty(context, console, "profileEnd", V8Console::profileEndCallback);
+ createBoundFunctionProperty(context, console, "timeline", V8Console::timelineCallback);
+ createBoundFunctionProperty(context, console, "timelineEnd", V8Console::timelineEndCallback);
+ createBoundFunctionProperty(context, console, "time", V8Console::timeCallback);
+ createBoundFunctionProperty(context, console, "timeEnd", V8Console::timeEndCallback);
+ createBoundFunctionProperty(context, console, "timeStamp", V8Console::timeStampCallback);
+
+ if (hasMemoryAttribute)
+ console->SetAccessorProperty(toV8StringInternalized(isolate, "memory"), v8::Function::New(isolate, V8Console::memoryGetterCallback, console), v8::Function::New(isolate, V8Console::memorySetterCallback), static_cast<v8::PropertyAttribute>(v8::None), v8::DEFAULT);
+
+ console->SetPrivate(context, inspectedContextPrivateKey(isolate), v8::External::New(isolate, inspectedContext));
+ return console;
+}
+
+v8::Local<v8::Object> V8Console::createCommandLineAPI(InspectedContext* inspectedContext)
+{
+ v8::Local<v8::Context> context = inspectedContext->context();
+ v8::Isolate* isolate = context->GetIsolate();
+ v8::MicrotasksScope microtasksScope(isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
+
+ v8::Local<v8::Object> commandLineAPI = v8::Object::New(isolate);
+
+ createBoundFunctionProperty(context, commandLineAPI, "dir", V8Console::dirCallback, "function dir(value) { [Command Line API] }");
+ createBoundFunctionProperty(context, commandLineAPI, "dirxml", V8Console::dirxmlCallback, "function dirxml(value) { [Command Line API] }");
+ createBoundFunctionProperty(context, commandLineAPI, "profile", V8Console::profileCallback, "function profile(title) { [Command Line API] }");
+ createBoundFunctionProperty(context, commandLineAPI, "profileEnd", V8Console::profileEndCallback, "function profileEnd(title) { [Command Line API] }");
+ createBoundFunctionProperty(context, commandLineAPI, "clear", V8Console::clearCallback, "function clear() { [Command Line API] }");
+ createBoundFunctionProperty(context, commandLineAPI, "table", V8Console::tableCallback, "function table(data, [columns]) { [Command Line API] }");
+
+ createBoundFunctionProperty(context, commandLineAPI, "keys", V8Console::keysCallback, "function keys(object) { [Command Line API] }");
+ createBoundFunctionProperty(context, commandLineAPI, "values", V8Console::valuesCallback, "function values(object) { [Command Line API] }");
+ createBoundFunctionProperty(context, commandLineAPI, "debug", V8Console::debugFunctionCallback, "function debug(function) { [Command Line API] }");
+ createBoundFunctionProperty(context, commandLineAPI, "undebug", V8Console::undebugFunctionCallback, "function undebug(function) { [Command Line API] }");
+ createBoundFunctionProperty(context, commandLineAPI, "monitor", V8Console::monitorFunctionCallback, "function monitor(function) { [Command Line API] }");
+ createBoundFunctionProperty(context, commandLineAPI, "unmonitor", V8Console::unmonitorFunctionCallback, "function unmonitor(function) { [Command Line API] }");
+ createBoundFunctionProperty(context, commandLineAPI, "inspect", V8Console::inspectCallback, "function inspect(object) { [Command Line API] }");
+ createBoundFunctionProperty(context, commandLineAPI, "copy", V8Console::copyCallback, "function copy(value) { [Command Line API] }");
+ createBoundFunctionProperty(context, commandLineAPI, "$_", V8Console::lastEvaluationResultCallback);
+ createBoundFunctionProperty(context, commandLineAPI, "$0", V8Console::inspectedObject0);
+ createBoundFunctionProperty(context, commandLineAPI, "$1", V8Console::inspectedObject1);
+ createBoundFunctionProperty(context, commandLineAPI, "$2", V8Console::inspectedObject2);
+ createBoundFunctionProperty(context, commandLineAPI, "$3", V8Console::inspectedObject3);
+ createBoundFunctionProperty(context, commandLineAPI, "$4", V8Console::inspectedObject4);
+
+ commandLineAPI->SetPrivate(context, inspectedContextPrivateKey(isolate), v8::External::New(isolate, inspectedContext));
+ return commandLineAPI;
+}
+
+void V8Console::clearInspectedContextIfNeeded(v8::Local<v8::Context> context, v8::Local<v8::Object> console)
+{
+ v8::Isolate* isolate = context->GetIsolate();
+ console->SetPrivate(context, inspectedContextPrivateKey(isolate), v8::External::New(isolate, nullptr));
+}
+
+bool V8Debugger::isCommandLineAPIMethod(const String16& name)
+{
+ static protocol::HashSet<String16> methods;
+ if (methods.size() == 0) {
+ const char* members[] = { "$", "$$", "$x", "dir", "dirxml", "keys", "values", "profile", "profileEnd",
+ "monitorEvents", "unmonitorEvents", "inspect", "copy", "clear", "getEventListeners",
+ "debug", "undebug", "monitor", "unmonitor", "table" };
+ for (size_t i = 0; i < PROTOCOL_ARRAY_LENGTH(members); ++i)
+ methods.add(members[i]);
+ }
+ return methods.find(name) != methods.end();
+}
+
+bool V8Debugger::isCommandLineAPIGetter(const String16& name)
+{
+ protocol::HashSet<String16> getters;
+ if (getters.size() == 0) {
+ const char* members[] = { "$0", "$1", "$2", "$3", "$4", "$_" };
+ for (size_t i = 0; i < PROTOCOL_ARRAY_LENGTH(members); ++i)
+ getters.add(members[i]);
+ }
+ return getters.find(name) != getters.end();
+}
+
+} // namespace blink
diff --git a/deps/v8_inspector/platform/v8_inspector/V8Console.h b/deps/v8_inspector/platform/v8_inspector/V8Console.h
new file mode 100644
index 0000000000..bd5fb8cd29
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8Console.h
@@ -0,0 +1,71 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8Console_h
+#define V8Console_h
+
+#include <v8.h>
+
+namespace blink {
+
+class InspectedContext;
+
+// Console API
+// https://console.spec.whatwg.org/#console-interface
+class V8Console {
+public:
+ static v8::Local<v8::Object> createConsole(InspectedContext*, bool hasMemoryAttribute);
+ static v8::Local<v8::Object> createCommandLineAPI(InspectedContext*);
+ static void clearInspectedContextIfNeeded(v8::Local<v8::Context>, v8::Local<v8::Object> console);
+
+private:
+ static void debugCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void errorCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void infoCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void logCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void warnCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void dirCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void dirxmlCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void tableCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void traceCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void groupCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void groupCollapsedCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void groupEndCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void clearCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void countCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void assertCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void markTimelineCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void profileCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void profileEndCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void timelineCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void timelineEndCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void timeCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void timeEndCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void timeStampCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ // TODO(philipj): There is no spec for the Memory Info API, see blink-dev:
+ // https://groups.google.com/a/chromium.org/d/msg/blink-dev/g5YRCGpC9vs/b4OJz71NmPwJ
+ static void memoryGetterCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void memorySetterCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+
+ // CommandLineAPI
+ static void keysCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void valuesCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void debugFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void undebugFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void monitorFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void unmonitorFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void lastEvaluationResultCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void inspectCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void copyCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void inspectedObject(const v8::FunctionCallbackInfo<v8::Value>&, unsigned num);
+ static void inspectedObject0(const v8::FunctionCallbackInfo<v8::Value>& info) { inspectedObject(info, 0); }
+ static void inspectedObject1(const v8::FunctionCallbackInfo<v8::Value>& info) { inspectedObject(info, 1); }
+ static void inspectedObject2(const v8::FunctionCallbackInfo<v8::Value>& info) { inspectedObject(info, 2); }
+ static void inspectedObject3(const v8::FunctionCallbackInfo<v8::Value>& info) { inspectedObject(info, 3); }
+ static void inspectedObject4(const v8::FunctionCallbackInfo<v8::Value>& info) { inspectedObject(info, 4); }
+};
+
+} // namespace blink
+
+#endif // V8Console_h
diff --git a/deps/v8_inspector/platform/v8_inspector/V8DebuggerAgentImpl.cpp b/deps/v8_inspector/platform/v8_inspector/V8DebuggerAgentImpl.cpp
new file mode 100644
index 0000000000..57cad6bdb3
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8DebuggerAgentImpl.cpp
@@ -0,0 +1,1455 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/v8_inspector/V8DebuggerAgentImpl.h"
+
+#include "platform/inspector_protocol/String16.h"
+#include "platform/inspector_protocol/Values.h"
+#include "platform/v8_inspector/InjectedScript.h"
+#include "platform/v8_inspector/InspectedContext.h"
+#include "platform/v8_inspector/JavaScriptCallFrame.h"
+#include "platform/v8_inspector/RemoteObjectId.h"
+#include "platform/v8_inspector/ScriptBreakpoint.h"
+#include "platform/v8_inspector/V8InspectorSessionImpl.h"
+#include "platform/v8_inspector/V8Regex.h"
+#include "platform/v8_inspector/V8RuntimeAgentImpl.h"
+#include "platform/v8_inspector/V8StackTraceImpl.h"
+#include "platform/v8_inspector/V8StringUtil.h"
+#include "platform/v8_inspector/public/V8ContentSearchUtil.h"
+#include "platform/v8_inspector/public/V8Debugger.h"
+#include "platform/v8_inspector/public/V8DebuggerClient.h"
+#include "platform/v8_inspector/public/V8ToProtocolValue.h"
+
+using blink::protocol::Array;
+using blink::protocol::Maybe;
+using blink::protocol::Debugger::BreakpointId;
+using blink::protocol::Debugger::CallFrame;
+using blink::protocol::Debugger::CollectionEntry;
+using blink::protocol::Runtime::ExceptionDetails;
+using blink::protocol::Debugger::FunctionDetails;
+using blink::protocol::Debugger::GeneratorObjectDetails;
+using blink::protocol::Runtime::ScriptId;
+using blink::protocol::Runtime::StackTrace;
+using blink::protocol::Runtime::RemoteObject;
+
+namespace {
+static const char v8AsyncTaskEventEnqueue[] = "enqueue";
+static const char v8AsyncTaskEventWillHandle[] = "willHandle";
+static const char v8AsyncTaskEventDidHandle[] = "didHandle";
+}
+
+namespace blink {
+
+namespace DebuggerAgentState {
+static const char javaScriptBreakpoints[] = "javaScriptBreakopints";
+static const char pauseOnExceptionsState[] = "pauseOnExceptionsState";
+static const char asyncCallStackDepth[] = "asyncCallStackDepth";
+static const char blackboxPattern[] = "blackboxPattern";
+static const char debuggerEnabled[] = "debuggerEnabled";
+
+// Breakpoint properties.
+static const char url[] = "url";
+static const char isRegex[] = "isRegex";
+static const char lineNumber[] = "lineNumber";
+static const char columnNumber[] = "columnNumber";
+static const char condition[] = "condition";
+static const char skipAllPauses[] = "skipAllPauses";
+
+} // namespace DebuggerAgentState;
+
+static const int maxSkipStepFrameCount = 128;
+
+static String16 breakpointIdSuffix(V8DebuggerAgentImpl::BreakpointSource source)
+{
+ switch (source) {
+ case V8DebuggerAgentImpl::UserBreakpointSource:
+ break;
+ case V8DebuggerAgentImpl::DebugCommandBreakpointSource:
+ return ":debug";
+ case V8DebuggerAgentImpl::MonitorCommandBreakpointSource:
+ return ":monitor";
+ }
+ return String16();
+}
+
+static String16 generateBreakpointId(const String16& scriptId, int lineNumber, int columnNumber, V8DebuggerAgentImpl::BreakpointSource source)
+{
+ return scriptId + ":" + String16::number(lineNumber) + ":" + String16::number(columnNumber) + breakpointIdSuffix(source);
+}
+
+static bool positionComparator(const std::pair<int, int>& a, const std::pair<int, int>& b)
+{
+ if (a.first != b.first)
+ return a.first < b.first;
+ return a.second < b.second;
+}
+
+static const LChar hexDigits[17] = "0123456789ABCDEF";
+
+static void appendUnsignedAsHex(unsigned number, String16Builder* destination)
+{
+ for (size_t i = 0; i < 8; ++i) {
+ destination->append(hexDigits[number & 0xF]);
+ number >>= 4;
+ }
+}
+
+// Hash algorithm for substrings is described in "Über die Komplexität der Multiplikation in
+// eingeschränkten Branchingprogrammmodellen" by Woelfe.
+// http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000
+static String16 calculateHash(const String16& str)
+{
+ static uint64_t prime[] = { 0x3FB75161, 0xAB1F4E4F, 0x82675BC5, 0xCD924D35, 0x81ABE279 };
+ static uint64_t random[] = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 };
+ static uint32_t randomOdd[] = { 0xB4663807, 0xCC322BF5, 0xD4F91BBD, 0xA7BEA11D, 0x8F462907 };
+
+ uint64_t hashes[] = { 0, 0, 0, 0, 0 };
+ uint64_t zi[] = { 1, 1, 1, 1, 1 };
+
+ const size_t hashesSize = PROTOCOL_ARRAY_LENGTH(hashes);
+
+ size_t current = 0;
+ const uint32_t* data = nullptr;
+ data = reinterpret_cast<const uint32_t*>(str.characters16());
+ for (size_t i = 0; i < str.sizeInBytes() / 4; i += 4) {
+ uint32_t v = data[i];
+ uint64_t xi = v * randomOdd[current] & 0x7FFFFFFF;
+ hashes[current] = (hashes[current] + zi[current] * xi) % prime[current];
+ zi[current] = (zi[current] * random[current]) % prime[current];
+ current = current == hashesSize - 1 ? 0 : current + 1;
+ }
+ if (str.sizeInBytes() % 4) {
+ uint32_t v = 0;
+ for (size_t i = str.sizeInBytes() - str.sizeInBytes() % 4; i < str.sizeInBytes(); ++i) {
+ v <<= 8;
+ v |= reinterpret_cast<const uint8_t*>(data)[i];
+ }
+ uint64_t xi = v * randomOdd[current] & 0x7FFFFFFF;
+ hashes[current] = (hashes[current] + zi[current] * xi) % prime[current];
+ zi[current] = (zi[current] * random[current]) % prime[current];
+ current = current == hashesSize - 1 ? 0 : current + 1;
+ }
+
+ for (size_t i = 0; i < hashesSize; ++i)
+ hashes[i] = (hashes[i] + zi[i] * (prime[i] - 1)) % prime[i];
+
+ String16Builder hash;
+ for (size_t i = 0; i < hashesSize; ++i)
+ appendUnsignedAsHex(hashes[i], &hash);
+ return hash.toString();
+}
+
+static bool hasInternalError(ErrorString* errorString, bool hasError)
+{
+ if (hasError)
+ *errorString = "Internal error";
+ return hasError;
+}
+
+static std::unique_ptr<protocol::Debugger::Location> buildProtocolLocation(const String16& scriptId, int lineNumber, int columnNumber)
+{
+ return protocol::Debugger::Location::create()
+ .setScriptId(scriptId)
+ .setLineNumber(lineNumber)
+ .setColumnNumber(columnNumber).build();
+}
+
+V8DebuggerAgentImpl::V8DebuggerAgentImpl(V8InspectorSessionImpl* session)
+ : m_debugger(session->debugger())
+ , m_session(session)
+ , m_enabled(false)
+ , m_state(nullptr)
+ , m_frontend(nullptr)
+ , m_isolate(m_debugger->isolate())
+ , m_breakReason(protocol::Debugger::Paused::ReasonEnum::Other)
+ , m_scheduledDebuggerStep(NoStep)
+ , m_skipNextDebuggerStepOut(false)
+ , m_javaScriptPauseScheduled(false)
+ , m_steppingFromFramework(false)
+ , m_pausingOnNativeEvent(false)
+ , m_skippedStepFrameCount(0)
+ , m_recursionLevelForStepOut(0)
+ , m_recursionLevelForStepFrame(0)
+ , m_skipAllPauses(false)
+ , m_maxAsyncCallStackDepth(0)
+{
+ clearBreakDetails();
+}
+
+V8DebuggerAgentImpl::~V8DebuggerAgentImpl()
+{
+}
+
+bool V8DebuggerAgentImpl::checkEnabled(ErrorString* errorString)
+{
+ if (enabled())
+ return true;
+ *errorString = "Debugger agent is not enabled";
+ return false;
+}
+
+void V8DebuggerAgentImpl::enable()
+{
+ // debugger().addListener may result in reporting all parsed scripts to
+ // the agent so it should already be in enabled state by then.
+ m_enabled = true;
+ m_state->setBoolean(DebuggerAgentState::debuggerEnabled, true);
+ debugger().debuggerAgentEnabled();
+
+ protocol::Vector<V8DebuggerParsedScript> compiledScripts;
+ debugger().getCompiledScripts(m_session->contextGroupId(), compiledScripts);
+ for (size_t i = 0; i < compiledScripts.size(); i++)
+ didParseSource(compiledScripts[i]);
+
+ // FIXME(WK44513): breakpoints activated flag should be synchronized between all front-ends
+ debugger().setBreakpointsActivated(true);
+ m_session->changeInstrumentationCounter(+1);
+}
+
+bool V8DebuggerAgentImpl::enabled()
+{
+ return m_enabled;
+}
+
+void V8DebuggerAgentImpl::enable(ErrorString* errorString)
+{
+ if (enabled())
+ return;
+
+ if (!m_session->client()->canExecuteScripts()) {
+ *errorString = "Script execution is prohibited";
+ return;
+ }
+
+ enable();
+ DCHECK(m_frontend);
+}
+
+void V8DebuggerAgentImpl::disable(ErrorString*)
+{
+ if (!enabled())
+ return;
+ m_session->changeInstrumentationCounter(-1);
+
+ m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, protocol::DictionaryValue::create());
+ m_state->setNumber(DebuggerAgentState::pauseOnExceptionsState, V8DebuggerImpl::DontPauseOnExceptions);
+ m_state->setNumber(DebuggerAgentState::asyncCallStackDepth, 0);
+
+ if (!m_pausedContext.IsEmpty())
+ debugger().continueProgram();
+ debugger().debuggerAgentDisabled();
+ m_pausedContext.Reset();
+ JavaScriptCallFrames emptyCallFrames;
+ m_pausedCallFrames.swap(emptyCallFrames);
+ m_scripts.clear();
+ m_blackboxedPositions.clear();
+ m_breakpointIdToDebuggerBreakpointIds.clear();
+ internalSetAsyncCallStackDepth(0);
+ m_continueToLocationBreakpointId = String16();
+ clearBreakDetails();
+ m_scheduledDebuggerStep = NoStep;
+ m_skipNextDebuggerStepOut = false;
+ m_javaScriptPauseScheduled = false;
+ m_steppingFromFramework = false;
+ m_pausingOnNativeEvent = false;
+ m_skippedStepFrameCount = 0;
+ m_recursionLevelForStepFrame = 0;
+ m_skipAllPauses = false;
+ m_blackboxPattern = nullptr;
+ m_state->remove(DebuggerAgentState::blackboxPattern);
+ m_enabled = false;
+ m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false);
+}
+
+void V8DebuggerAgentImpl::internalSetAsyncCallStackDepth(int depth)
+{
+ if (depth <= 0) {
+ m_maxAsyncCallStackDepth = 0;
+ allAsyncTasksCanceled();
+ } else {
+ m_maxAsyncCallStackDepth = depth;
+ }
+}
+
+void V8DebuggerAgentImpl::setInspectorState(protocol::DictionaryValue* state)
+{
+ m_state = state;
+}
+
+void V8DebuggerAgentImpl::clearFrontend()
+{
+ ErrorString error;
+ disable(&error);
+ DCHECK(m_frontend);
+ m_frontend = nullptr;
+}
+
+void V8DebuggerAgentImpl::restore()
+{
+ DCHECK(!m_enabled);
+ if (!m_state->booleanProperty(DebuggerAgentState::debuggerEnabled, false))
+ return;
+ if (!m_session->client()->canExecuteScripts())
+ return;
+
+ enable();
+ ErrorString error;
+
+ int pauseState = V8DebuggerImpl::DontPauseOnExceptions;
+ m_state->getNumber(DebuggerAgentState::pauseOnExceptionsState, &pauseState);
+ setPauseOnExceptionsImpl(&error, pauseState);
+ DCHECK(error.isEmpty());
+
+ m_skipAllPauses = m_state->booleanProperty(DebuggerAgentState::skipAllPauses, false);
+
+ int asyncCallStackDepth = 0;
+ m_state->getNumber(DebuggerAgentState::asyncCallStackDepth, &asyncCallStackDepth);
+ internalSetAsyncCallStackDepth(asyncCallStackDepth);
+
+ String16 blackboxPattern;
+ if (m_state->getString(DebuggerAgentState::blackboxPattern, &blackboxPattern)) {
+ if (!setBlackboxPattern(&error, blackboxPattern))
+ NOTREACHED();
+ }
+}
+
+void V8DebuggerAgentImpl::setBreakpointsActive(ErrorString* errorString, bool active)
+{
+ if (!checkEnabled(errorString))
+ return;
+ debugger().setBreakpointsActivated(active);
+}
+
+void V8DebuggerAgentImpl::setSkipAllPauses(ErrorString*, bool skipped)
+{
+ m_skipAllPauses = skipped;
+ m_state->setBoolean(DebuggerAgentState::skipAllPauses, m_skipAllPauses);
+}
+
+static std::unique_ptr<protocol::DictionaryValue> buildObjectForBreakpointCookie(const String16& url, int lineNumber, int columnNumber, const String16& condition, bool isRegex)
+{
+ std::unique_ptr<protocol::DictionaryValue> breakpointObject = protocol::DictionaryValue::create();
+ breakpointObject->setString(DebuggerAgentState::url, url);
+ breakpointObject->setNumber(DebuggerAgentState::lineNumber, lineNumber);
+ breakpointObject->setNumber(DebuggerAgentState::columnNumber, columnNumber);
+ breakpointObject->setString(DebuggerAgentState::condition, condition);
+ breakpointObject->setBoolean(DebuggerAgentState::isRegex, isRegex);
+ return breakpointObject;
+}
+
+static bool matches(V8DebuggerImpl* debugger, const String16& url, const String16& pattern, bool isRegex)
+{
+ if (isRegex) {
+ V8Regex regex(debugger, pattern, true);
+ return regex.match(url) != -1;
+ }
+ return url == pattern;
+}
+
+void V8DebuggerAgentImpl::setBreakpointByUrl(ErrorString* errorString,
+ int lineNumber,
+ const Maybe<String16>& optionalURL,
+ const Maybe<String16>& optionalURLRegex,
+ const Maybe<int>& optionalColumnNumber,
+ const Maybe<String16>& optionalCondition,
+ String16* outBreakpointId,
+ std::unique_ptr<protocol::Array<protocol::Debugger::Location>>* locations)
+{
+ *locations = Array<protocol::Debugger::Location>::create();
+ if (optionalURL.isJust() == optionalURLRegex.isJust()) {
+ *errorString = "Either url or urlRegex must be specified.";
+ return;
+ }
+
+ String16 url = optionalURL.isJust() ? optionalURL.fromJust() : optionalURLRegex.fromJust();
+ int columnNumber = 0;
+ if (optionalColumnNumber.isJust()) {
+ columnNumber = optionalColumnNumber.fromJust();
+ if (columnNumber < 0) {
+ *errorString = "Incorrect column number";
+ return;
+ }
+ }
+ String16 condition = optionalCondition.fromMaybe("");
+ bool isRegex = optionalURLRegex.isJust();
+
+ String16 breakpointId = (isRegex ? "/" + url + "/" : url) + ":" + String16::number(lineNumber) + ":" + String16::number(columnNumber);
+ protocol::DictionaryValue* breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints);
+ if (!breakpointsCookie) {
+ std::unique_ptr<protocol::DictionaryValue> newValue = protocol::DictionaryValue::create();
+ breakpointsCookie = newValue.get();
+ m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, std::move(newValue));
+ }
+ if (breakpointsCookie->get(breakpointId)) {
+ *errorString = "Breakpoint at specified location already exists.";
+ return;
+ }
+
+ breakpointsCookie->setObject(breakpointId, buildObjectForBreakpointCookie(url, lineNumber, columnNumber, condition, isRegex));
+
+ ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition);
+ for (auto& script : m_scripts) {
+ if (!matches(m_debugger, script.second->sourceURL(), url, isRegex))
+ continue;
+ std::unique_ptr<protocol::Debugger::Location> location = resolveBreakpoint(breakpointId, script.first, breakpoint, UserBreakpointSource);
+ if (location)
+ (*locations)->addItem(std::move(location));
+ }
+
+ *outBreakpointId = breakpointId;
+}
+
+static bool parseLocation(ErrorString* errorString, std::unique_ptr<protocol::Debugger::Location> location, String16* scriptId, int* lineNumber, int* columnNumber)
+{
+ *scriptId = location->getScriptId();
+ *lineNumber = location->getLineNumber();
+ *columnNumber = location->getColumnNumber(0);
+ return true;
+}
+
+void V8DebuggerAgentImpl::setBreakpoint(ErrorString* errorString,
+ std::unique_ptr<protocol::Debugger::Location> location,
+ const Maybe<String16>& optionalCondition,
+ String16* outBreakpointId,
+ std::unique_ptr<protocol::Debugger::Location>* actualLocation)
+{
+ String16 scriptId;
+ int lineNumber;
+ int columnNumber;
+
+ if (!parseLocation(errorString, std::move(location), &scriptId, &lineNumber, &columnNumber))
+ return;
+
+ String16 condition = optionalCondition.fromMaybe("");
+
+ String16 breakpointId = generateBreakpointId(scriptId, lineNumber, columnNumber, UserBreakpointSource);
+ if (m_breakpointIdToDebuggerBreakpointIds.contains(breakpointId)) {
+ *errorString = "Breakpoint at specified location already exists.";
+ return;
+ }
+ ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition);
+ *actualLocation = resolveBreakpoint(breakpointId, scriptId, breakpoint, UserBreakpointSource);
+ if (*actualLocation)
+ *outBreakpointId = breakpointId;
+ else
+ *errorString = "Could not resolve breakpoint";
+}
+
+void V8DebuggerAgentImpl::removeBreakpoint(ErrorString* errorString, const String16& breakpointId)
+{
+ if (!checkEnabled(errorString))
+ return;
+ protocol::DictionaryValue* breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints);
+ if (breakpointsCookie)
+ breakpointsCookie->remove(breakpointId);
+ removeBreakpoint(breakpointId);
+}
+
+void V8DebuggerAgentImpl::removeBreakpoint(const String16& breakpointId)
+{
+ DCHECK(enabled());
+ BreakpointIdToDebuggerBreakpointIdsMap::iterator debuggerBreakpointIdsIterator = m_breakpointIdToDebuggerBreakpointIds.find(breakpointId);
+ if (debuggerBreakpointIdsIterator == m_breakpointIdToDebuggerBreakpointIds.end())
+ return;
+ protocol::Vector<String16>* ids = debuggerBreakpointIdsIterator->second;
+ for (size_t i = 0; i < ids->size(); ++i) {
+ const String16& debuggerBreakpointId = ids->at(i);
+
+ debugger().removeBreakpoint(debuggerBreakpointId);
+ m_serverBreakpoints.remove(debuggerBreakpointId);
+ }
+ m_breakpointIdToDebuggerBreakpointIds.remove(breakpointId);
+}
+
+void V8DebuggerAgentImpl::continueToLocation(ErrorString* errorString,
+ std::unique_ptr<protocol::Debugger::Location> location,
+ const protocol::Maybe<bool>& interstateLocationOpt)
+{
+ if (!checkEnabled(errorString))
+ return;
+ if (!m_continueToLocationBreakpointId.isEmpty()) {
+ debugger().removeBreakpoint(m_continueToLocationBreakpointId);
+ m_continueToLocationBreakpointId = "";
+ }
+
+ String16 scriptId;
+ int lineNumber;
+ int columnNumber;
+
+ if (!parseLocation(errorString, std::move(location), &scriptId, &lineNumber, &columnNumber))
+ return;
+
+ ScriptBreakpoint breakpoint(lineNumber, columnNumber, "");
+ m_continueToLocationBreakpointId = debugger().setBreakpoint(scriptId, breakpoint, &lineNumber, &columnNumber, interstateLocationOpt.fromMaybe(false));
+ resume(errorString);
+}
+
+void V8DebuggerAgentImpl::getBacktrace(ErrorString* errorString, std::unique_ptr<Array<CallFrame>>* callFrames, Maybe<StackTrace>* asyncStackTrace)
+{
+ if (!assertPaused(errorString))
+ return;
+ m_pausedCallFrames.swap(debugger().currentCallFrames());
+ *callFrames = currentCallFrames(errorString);
+ if (!*callFrames)
+ return;
+ *asyncStackTrace = currentAsyncStackTrace();
+}
+
+bool V8DebuggerAgentImpl::isCurrentCallStackEmptyOrBlackboxed()
+{
+ DCHECK(enabled());
+ JavaScriptCallFrames callFrames = debugger().currentCallFrames();
+ for (size_t index = 0; index < callFrames.size(); ++index) {
+ if (!isCallFrameWithUnknownScriptOrBlackboxed(callFrames[index]))
+ return false;
+ }
+ return true;
+}
+
+bool V8DebuggerAgentImpl::isTopPausedCallFrameBlackboxed()
+{
+ DCHECK(enabled());
+ return isCallFrameWithUnknownScriptOrBlackboxed(m_pausedCallFrames.size() ? m_pausedCallFrames[0] : nullptr);
+}
+
+bool V8DebuggerAgentImpl::isCallFrameWithUnknownScriptOrBlackboxed(JavaScriptCallFrame* frame)
+{
+ if (!frame)
+ return true;
+ ScriptsMap::iterator it = m_scripts.find(String16::number(frame->sourceID()));
+ if (it == m_scripts.end()) {
+ // Unknown scripts are blackboxed.
+ return true;
+ }
+ if (m_blackboxPattern) {
+ String16 scriptSourceURL = it->second->sourceURL();
+ if (!scriptSourceURL.isEmpty() && m_blackboxPattern->match(scriptSourceURL) != -1)
+ return true;
+ }
+ auto itBlackboxedPositions = m_blackboxedPositions.find(String16::number(frame->sourceID()));
+ if (itBlackboxedPositions == m_blackboxedPositions.end())
+ return false;
+
+ protocol::Vector<std::pair<int, int>>* ranges = itBlackboxedPositions->second;
+ auto itRange = std::lower_bound(ranges->begin(), ranges->end(), std::make_pair(frame->line(), frame->column()), positionComparator);
+ // Ranges array contains positions in script where blackbox state is changed.
+ // [(0,0) ... ranges[0]) isn't blackboxed, [ranges[0] ... ranges[1]) is blackboxed...
+ return std::distance(ranges->begin(), itRange) % 2;
+}
+
+V8DebuggerAgentImpl::SkipPauseRequest V8DebuggerAgentImpl::shouldSkipExceptionPause(JavaScriptCallFrame* topCallFrame)
+{
+ if (m_steppingFromFramework)
+ return RequestNoSkip;
+ if (isCallFrameWithUnknownScriptOrBlackboxed(topCallFrame))
+ return RequestContinue;
+ return RequestNoSkip;
+}
+
+V8DebuggerAgentImpl::SkipPauseRequest V8DebuggerAgentImpl::shouldSkipStepPause(JavaScriptCallFrame* topCallFrame)
+{
+ if (m_steppingFromFramework)
+ return RequestNoSkip;
+
+ if (m_skipNextDebuggerStepOut) {
+ m_skipNextDebuggerStepOut = false;
+ if (m_scheduledDebuggerStep == StepOut)
+ return RequestStepOut;
+ }
+
+ if (!isCallFrameWithUnknownScriptOrBlackboxed(topCallFrame))
+ return RequestNoSkip;
+
+ if (m_skippedStepFrameCount >= maxSkipStepFrameCount)
+ return RequestStepOut;
+
+ if (!m_skippedStepFrameCount)
+ m_recursionLevelForStepFrame = 1;
+
+ ++m_skippedStepFrameCount;
+ return RequestStepFrame;
+}
+
+std::unique_ptr<protocol::Debugger::Location> V8DebuggerAgentImpl::resolveBreakpoint(const String16& breakpointId, const String16& scriptId, const ScriptBreakpoint& breakpoint, BreakpointSource source)
+{
+ DCHECK(enabled());
+ // FIXME: remove these checks once crbug.com/520702 is resolved.
+ CHECK(!breakpointId.isEmpty());
+ CHECK(!scriptId.isEmpty());
+ ScriptsMap::iterator scriptIterator = m_scripts.find(scriptId);
+ if (scriptIterator == m_scripts.end())
+ return nullptr;
+ V8DebuggerScript* script = scriptIterator->second;
+ if (breakpoint.lineNumber < script->startLine() || script->endLine() < breakpoint.lineNumber)
+ return nullptr;
+
+ int actualLineNumber;
+ int actualColumnNumber;
+ String16 debuggerBreakpointId = debugger().setBreakpoint(scriptId, breakpoint, &actualLineNumber, &actualColumnNumber, false);
+ if (debuggerBreakpointId.isEmpty())
+ return nullptr;
+
+ m_serverBreakpoints.set(debuggerBreakpointId, std::make_pair(breakpointId, source));
+ CHECK(!breakpointId.isEmpty());
+ if (!m_breakpointIdToDebuggerBreakpointIds.contains(breakpointId))
+ m_breakpointIdToDebuggerBreakpointIds.set(breakpointId, protocol::Vector<String16>());
+
+ BreakpointIdToDebuggerBreakpointIdsMap::iterator debuggerBreakpointIdsIterator = m_breakpointIdToDebuggerBreakpointIds.find(breakpointId);
+ debuggerBreakpointIdsIterator->second->append(debuggerBreakpointId);
+
+ return buildProtocolLocation(scriptId, actualLineNumber, actualColumnNumber);
+}
+
+void V8DebuggerAgentImpl::searchInContent(ErrorString* error, const String16& scriptId, const String16& query,
+ const Maybe<bool>& optionalCaseSensitive,
+ const Maybe<bool>& optionalIsRegex,
+ std::unique_ptr<Array<protocol::Debugger::SearchMatch>>* results)
+{
+ ScriptsMap::iterator it = m_scripts.find(scriptId);
+ if (it != m_scripts.end())
+ *results = V8ContentSearchUtil::searchInTextByLines(m_session, it->second->source(), query, optionalCaseSensitive.fromMaybe(false), optionalIsRegex.fromMaybe(false));
+ else
+ *error = String16("No script for id: " + scriptId);
+}
+
+void V8DebuggerAgentImpl::setScriptSource(ErrorString* errorString,
+ const String16& scriptId,
+ const String16& newContent,
+ const Maybe<bool>& preview,
+ Maybe<protocol::Array<protocol::Debugger::CallFrame>>* newCallFrames,
+ Maybe<bool>* stackChanged,
+ Maybe<StackTrace>* asyncStackTrace,
+ Maybe<protocol::Debugger::SetScriptSourceError>* optOutCompileError)
+{
+ if (!checkEnabled(errorString))
+ return;
+ if (!debugger().setScriptSource(scriptId, newContent, preview.fromMaybe(false), errorString, optOutCompileError, &m_pausedCallFrames, stackChanged))
+ return;
+
+ std::unique_ptr<Array<CallFrame>> callFrames = currentCallFrames(errorString);
+ if (!callFrames)
+ return;
+ *newCallFrames = std::move(callFrames);
+ *asyncStackTrace = currentAsyncStackTrace();
+
+ ScriptsMap::iterator it = m_scripts.find(scriptId);
+ if (it == m_scripts.end())
+ return;
+ it->second->setSource(newContent);
+}
+
+void V8DebuggerAgentImpl::restartFrame(ErrorString* errorString,
+ const String16& callFrameId,
+ std::unique_ptr<Array<CallFrame>>* newCallFrames,
+ Maybe<StackTrace>* asyncStackTrace)
+{
+ if (!assertPaused(errorString))
+ return;
+ InjectedScript::CallFrameScope scope(errorString, m_debugger, m_session->contextGroupId(), callFrameId);
+ if (!scope.initialize())
+ return;
+ if (scope.frameOrdinal() >= m_pausedCallFrames.size()) {
+ *errorString = "Could not find call frame with given id";
+ return;
+ }
+
+ v8::Local<v8::Value> resultValue;
+ v8::Local<v8::Boolean> result;
+ if (!m_pausedCallFrames[scope.frameOrdinal()]->restart().ToLocal(&resultValue) || scope.tryCatch().HasCaught() || !resultValue->ToBoolean(scope.context()).ToLocal(&result) || !result->Value()) {
+ *errorString = "Internal error";
+ return;
+ }
+ m_pausedCallFrames.swap(debugger().currentCallFrames());
+
+ *newCallFrames = currentCallFrames(errorString);
+ if (!*newCallFrames)
+ return;
+ *asyncStackTrace = currentAsyncStackTrace();
+}
+
+void V8DebuggerAgentImpl::getScriptSource(ErrorString* error, const String16& scriptId, String16* scriptSource)
+{
+ if (!checkEnabled(error))
+ return;
+ ScriptsMap::iterator it = m_scripts.find(scriptId);
+ if (it == m_scripts.end()) {
+ *error = "No script for id: " + scriptId;
+ return;
+ }
+ *scriptSource = it->second->source();
+}
+
+void V8DebuggerAgentImpl::getFunctionDetails(ErrorString* errorString, const String16& functionId, std::unique_ptr<FunctionDetails>* details)
+{
+ if (!checkEnabled(errorString))
+ return;
+ InjectedScript::ObjectScope scope(errorString, m_debugger, m_session->contextGroupId(), functionId);
+ if (!scope.initialize())
+ return;
+ if (!scope.object()->IsFunction()) {
+ *errorString = "Value with given id is not a function";
+ return;
+ }
+ v8::Local<v8::Function> function = scope.object().As<v8::Function>();
+
+ v8::Local<v8::Value> scopesValue;
+ v8::Local<v8::Array> scopes;
+ if (m_debugger->functionScopes(function).ToLocal(&scopesValue) && scopesValue->IsArray()) {
+ scopes = scopesValue.As<v8::Array>();
+ if (!scope.injectedScript()->wrapPropertyInArray(errorString, scopes, toV8StringInternalized(m_isolate, "object"), scope.objectGroupName()))
+ return;
+ }
+
+ std::unique_ptr<FunctionDetails> functionDetails = FunctionDetails::create()
+ .setLocation(buildProtocolLocation(String16::number(function->ScriptId()), function->GetScriptLineNumber(), function->GetScriptColumnNumber()))
+ .setFunctionName(toProtocolStringWithTypeCheck(function->GetDebugName()))
+ .setIsGenerator(function->IsGeneratorFunction()).build();
+
+ if (!scopes.IsEmpty()) {
+ protocol::ErrorSupport errorSupport;
+ std::unique_ptr<protocol::Array<protocol::Debugger::Scope>> scopeChain = protocol::Array<protocol::Debugger::Scope>::parse(toProtocolValue(scope.context(), scopes).get(), &errorSupport);
+ if (hasInternalError(errorString, errorSupport.hasErrors()))
+ return;
+ functionDetails->setScopeChain(std::move(scopeChain));
+ }
+
+ *details = std::move(functionDetails);
+}
+
+void V8DebuggerAgentImpl::getGeneratorObjectDetails(ErrorString* errorString, const String16& objectId, std::unique_ptr<GeneratorObjectDetails>* outDetails)
+{
+ if (!checkEnabled(errorString))
+ return;
+ InjectedScript::ObjectScope scope(errorString, m_debugger, m_session->contextGroupId(), objectId);
+ if (!scope.initialize())
+ return;
+ if (!scope.object()->IsObject()) {
+ *errorString = "Value with given id is not an Object";
+ return;
+ }
+ v8::Local<v8::Object> object = scope.object().As<v8::Object>();
+
+ v8::Local<v8::Object> detailsObject;
+ v8::Local<v8::Value> detailsValue = debugger().generatorObjectDetails(object);
+ if (hasInternalError(errorString, !detailsValue->IsObject() || !detailsValue->ToObject(scope.context()).ToLocal(&detailsObject)))
+ return;
+
+ if (!scope.injectedScript()->wrapObjectProperty(errorString, detailsObject, toV8StringInternalized(m_isolate, "function"), scope.objectGroupName()))
+ return;
+
+ protocol::ErrorSupport errors;
+ std::unique_ptr<GeneratorObjectDetails> protocolDetails = GeneratorObjectDetails::parse(toProtocolValue(scope.context(), detailsObject).get(), &errors);
+ if (hasInternalError(errorString, !protocolDetails))
+ return;
+ *outDetails = std::move(protocolDetails);
+}
+
+void V8DebuggerAgentImpl::getCollectionEntries(ErrorString* errorString, const String16& objectId, std::unique_ptr<protocol::Array<CollectionEntry>>* outEntries)
+{
+ if (!checkEnabled(errorString))
+ return;
+ InjectedScript::ObjectScope scope(errorString, m_debugger, m_session->contextGroupId(), objectId);
+ if (!scope.initialize())
+ return;
+ if (!scope.object()->IsObject()) {
+ *errorString = "Object with given id is not a collection";
+ return;
+ }
+ v8::Local<v8::Object> object = scope.object().As<v8::Object>();
+
+ v8::Local<v8::Value> entriesValue = m_debugger->collectionEntries(object);
+ if (hasInternalError(errorString, entriesValue.IsEmpty()))
+ return;
+ if (entriesValue->IsUndefined()) {
+ *errorString = "Object with given id is not a collection";
+ return;
+ }
+ if (hasInternalError(errorString, !entriesValue->IsArray()))
+ return;
+ v8::Local<v8::Array> entriesArray = entriesValue.As<v8::Array>();
+ if (!scope.injectedScript()->wrapPropertyInArray(errorString, entriesArray, toV8StringInternalized(m_isolate, "key"), scope.objectGroupName()))
+ return;
+ if (!scope.injectedScript()->wrapPropertyInArray(errorString, entriesArray, toV8StringInternalized(m_isolate, "value"), scope.objectGroupName()))
+ return;
+ protocol::ErrorSupport errors;
+ std::unique_ptr<protocol::Array<CollectionEntry>> entries = protocol::Array<CollectionEntry>::parse(toProtocolValue(scope.context(), entriesArray).get(), &errors);
+ if (hasInternalError(errorString, !entries))
+ return;
+ *outEntries = std::move(entries);
+}
+
+void V8DebuggerAgentImpl::schedulePauseOnNextStatement(const String16& breakReason, std::unique_ptr<protocol::DictionaryValue> data)
+{
+ if (!enabled() || m_scheduledDebuggerStep == StepInto || m_javaScriptPauseScheduled || debugger().isPaused() || !debugger().breakpointsActivated())
+ return;
+ m_breakReason = breakReason;
+ m_breakAuxData = std::move(data);
+ m_pausingOnNativeEvent = true;
+ m_skipNextDebuggerStepOut = false;
+ debugger().setPauseOnNextStatement(true);
+}
+
+void V8DebuggerAgentImpl::schedulePauseOnNextStatementIfSteppingInto()
+{
+ DCHECK(enabled());
+ if (m_scheduledDebuggerStep != StepInto || m_javaScriptPauseScheduled || debugger().isPaused())
+ return;
+ clearBreakDetails();
+ m_pausingOnNativeEvent = false;
+ m_skippedStepFrameCount = 0;
+ m_recursionLevelForStepFrame = 0;
+ debugger().setPauseOnNextStatement(true);
+}
+
+void V8DebuggerAgentImpl::cancelPauseOnNextStatement()
+{
+ if (m_javaScriptPauseScheduled || debugger().isPaused())
+ return;
+ clearBreakDetails();
+ m_pausingOnNativeEvent = false;
+ debugger().setPauseOnNextStatement(false);
+}
+
+bool V8DebuggerAgentImpl::v8AsyncTaskEventsEnabled() const
+{
+ return m_maxAsyncCallStackDepth;
+}
+
+void V8DebuggerAgentImpl::didReceiveV8AsyncTaskEvent(v8::Local<v8::Context> context, const String16& eventType, const String16& eventName, int id)
+{
+ DCHECK(m_maxAsyncCallStackDepth);
+ // The scopes for the ids are defined by the eventName namespaces. There are currently two namespaces: "Object." and "Promise.".
+ void* ptr = reinterpret_cast<void*>(id * 4 + (eventName[0] == 'P' ? 2 : 0) + 1);
+ if (eventType == v8AsyncTaskEventEnqueue)
+ asyncTaskScheduled(eventName, ptr, false);
+ else if (eventType == v8AsyncTaskEventWillHandle)
+ asyncTaskStarted(ptr);
+ else if (eventType == v8AsyncTaskEventDidHandle)
+ asyncTaskFinished(ptr);
+ else
+ NOTREACHED();
+}
+
+void V8DebuggerAgentImpl::pause(ErrorString* errorString)
+{
+ if (!checkEnabled(errorString))
+ return;
+ if (m_javaScriptPauseScheduled || debugger().isPaused())
+ return;
+ clearBreakDetails();
+ m_javaScriptPauseScheduled = true;
+ m_scheduledDebuggerStep = NoStep;
+ m_skippedStepFrameCount = 0;
+ m_steppingFromFramework = false;
+ debugger().setPauseOnNextStatement(true);
+}
+
+void V8DebuggerAgentImpl::resume(ErrorString* errorString)
+{
+ if (!assertPaused(errorString))
+ return;
+ m_scheduledDebuggerStep = NoStep;
+ m_steppingFromFramework = false;
+ m_session->releaseObjectGroup(V8InspectorSession::backtraceObjectGroup);
+ debugger().continueProgram();
+}
+
+void V8DebuggerAgentImpl::stepOver(ErrorString* errorString)
+{
+ if (!assertPaused(errorString))
+ return;
+ // StepOver at function return point should fallback to StepInto.
+ JavaScriptCallFrame* frame = m_pausedCallFrames.size() ? m_pausedCallFrames[0] : nullptr;
+ if (frame && frame->isAtReturn()) {
+ stepInto(errorString);
+ return;
+ }
+ m_scheduledDebuggerStep = StepOver;
+ m_steppingFromFramework = isTopPausedCallFrameBlackboxed();
+ m_session->releaseObjectGroup(V8InspectorSession::backtraceObjectGroup);
+ debugger().stepOverStatement();
+}
+
+void V8DebuggerAgentImpl::stepInto(ErrorString* errorString)
+{
+ if (!assertPaused(errorString))
+ return;
+ m_scheduledDebuggerStep = StepInto;
+ m_steppingFromFramework = isTopPausedCallFrameBlackboxed();
+ m_session->releaseObjectGroup(V8InspectorSession::backtraceObjectGroup);
+ debugger().stepIntoStatement();
+}
+
+void V8DebuggerAgentImpl::stepOut(ErrorString* errorString)
+{
+ if (!assertPaused(errorString))
+ return;
+ m_scheduledDebuggerStep = StepOut;
+ m_skipNextDebuggerStepOut = false;
+ m_recursionLevelForStepOut = 1;
+ m_steppingFromFramework = isTopPausedCallFrameBlackboxed();
+ m_session->releaseObjectGroup(V8InspectorSession::backtraceObjectGroup);
+ debugger().stepOutOfFunction();
+}
+
+void V8DebuggerAgentImpl::setPauseOnExceptions(ErrorString* errorString, const String16& stringPauseState)
+{
+ if (!checkEnabled(errorString))
+ return;
+ V8DebuggerImpl::PauseOnExceptionsState pauseState;
+ if (stringPauseState == "none") {
+ pauseState = V8DebuggerImpl::DontPauseOnExceptions;
+ } else if (stringPauseState == "all") {
+ pauseState = V8DebuggerImpl::PauseOnAllExceptions;
+ } else if (stringPauseState == "uncaught") {
+ pauseState = V8DebuggerImpl::PauseOnUncaughtExceptions;
+ } else {
+ *errorString = "Unknown pause on exceptions mode: " + stringPauseState;
+ return;
+ }
+ setPauseOnExceptionsImpl(errorString, pauseState);
+}
+
+void V8DebuggerAgentImpl::setPauseOnExceptionsImpl(ErrorString* errorString, int pauseState)
+{
+ debugger().setPauseOnExceptionsState(static_cast<V8DebuggerImpl::PauseOnExceptionsState>(pauseState));
+ if (debugger().getPauseOnExceptionsState() != pauseState)
+ *errorString = "Internal error. Could not change pause on exceptions state";
+ else
+ m_state->setNumber(DebuggerAgentState::pauseOnExceptionsState, pauseState);
+}
+
+void V8DebuggerAgentImpl::evaluateOnCallFrame(ErrorString* errorString,
+ const String16& callFrameId,
+ const String16& expression,
+ const Maybe<String16>& objectGroup,
+ const Maybe<bool>& includeCommandLineAPI,
+ const Maybe<bool>& doNotPauseOnExceptionsAndMuteConsole,
+ const Maybe<bool>& returnByValue,
+ const Maybe<bool>& generatePreview,
+ std::unique_ptr<RemoteObject>* result,
+ Maybe<bool>* wasThrown,
+ Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails)
+{
+ if (!assertPaused(errorString))
+ return;
+ InjectedScript::CallFrameScope scope(errorString, m_debugger, m_session->contextGroupId(), callFrameId);
+ if (!scope.initialize())
+ return;
+ if (scope.frameOrdinal() >= m_pausedCallFrames.size()) {
+ *errorString = "Could not find call frame with given id";
+ return;
+ }
+
+ if (includeCommandLineAPI.fromMaybe(false) && !scope.installCommandLineAPI())
+ return;
+ if (doNotPauseOnExceptionsAndMuteConsole.fromMaybe(false))
+ scope.ignoreExceptionsAndMuteConsole();
+
+ v8::MaybeLocal<v8::Value> maybeResultValue = m_pausedCallFrames[scope.frameOrdinal()]->evaluate(toV8String(m_isolate, expression));
+
+ // Re-initialize after running client's code, as it could have destroyed context or session.
+ if (!scope.initialize())
+ return;
+ scope.injectedScript()->wrapEvaluateResult(errorString,
+ maybeResultValue,
+ scope.tryCatch(),
+ objectGroup.fromMaybe(""),
+ returnByValue.fromMaybe(false),
+ generatePreview.fromMaybe(false),
+ result,
+ wasThrown,
+ exceptionDetails);
+}
+
+void V8DebuggerAgentImpl::setVariableValue(ErrorString* errorString,
+ int scopeNumber,
+ const String16& variableName,
+ std::unique_ptr<protocol::Runtime::CallArgument> newValueArgument,
+ const String16& callFrameId)
+{
+ if (!checkEnabled(errorString))
+ return;
+ if (!assertPaused(errorString))
+ return;
+ InjectedScript::CallFrameScope scope(errorString, m_debugger, m_session->contextGroupId(), callFrameId);
+ if (!scope.initialize())
+ return;
+
+ v8::Local<v8::Value> newValue;
+ if (!scope.injectedScript()->resolveCallArgument(errorString, newValueArgument.get()).ToLocal(&newValue))
+ return;
+
+ if (scope.frameOrdinal() >= m_pausedCallFrames.size()) {
+ *errorString = "Could not find call frame with given id";
+ return;
+ }
+ v8::MaybeLocal<v8::Value> result = m_pausedCallFrames[scope.frameOrdinal()]->setVariableValue(scopeNumber, toV8String(m_isolate, variableName), newValue);
+ if (scope.tryCatch().HasCaught() || result.IsEmpty()) {
+ *errorString = "Internal error";
+ return;
+ }
+}
+
+void V8DebuggerAgentImpl::setAsyncCallStackDepth(ErrorString* errorString, int depth)
+{
+ if (!checkEnabled(errorString))
+ return;
+ m_state->setNumber(DebuggerAgentState::asyncCallStackDepth, depth);
+ internalSetAsyncCallStackDepth(depth);
+}
+
+void V8DebuggerAgentImpl::asyncTaskScheduled(const String16& taskName, void* task, bool recurring)
+{
+ if (!m_maxAsyncCallStackDepth)
+ return;
+ v8::HandleScope scope(m_isolate);
+ std::unique_ptr<V8StackTraceImpl> chain = V8StackTraceImpl::capture(this, V8StackTrace::maxCallStackSizeToCapture, taskName);
+ if (chain) {
+ m_asyncTaskStacks.set(task, std::move(chain));
+ if (recurring)
+ m_recurringTasks.add(task);
+ }
+}
+
+void V8DebuggerAgentImpl::asyncTaskCanceled(void* task)
+{
+ if (!m_maxAsyncCallStackDepth)
+ return;
+ m_asyncTaskStacks.remove(task);
+ m_recurringTasks.remove(task);
+}
+
+void V8DebuggerAgentImpl::asyncTaskStarted(void* task)
+{
+ // Not enabled, return.
+ if (!m_maxAsyncCallStackDepth)
+ return;
+
+ V8StackTraceImpl* stack = m_asyncTaskStacks.get(task);
+ // Needs to support following order of events:
+ // - asyncTaskScheduled
+ // <-- attached here -->
+ // - asyncTaskStarted
+ // - asyncTaskCanceled <-- canceled before finished
+ // <-- async stack requested here -->
+ // - asyncTaskFinished
+ m_currentStacks.append(stack ? stack->clone() : nullptr);
+}
+
+void V8DebuggerAgentImpl::asyncTaskFinished(void* task)
+{
+ if (!m_maxAsyncCallStackDepth)
+ return;
+ // We could start instrumenting half way and the stack is empty.
+ if (!m_currentStacks.size())
+ return;
+
+ m_currentStacks.removeLast();
+ if (!m_recurringTasks.contains(task))
+ m_asyncTaskStacks.remove(task);
+}
+
+void V8DebuggerAgentImpl::allAsyncTasksCanceled()
+{
+ m_asyncTaskStacks.clear();
+ m_recurringTasks.clear();
+ m_currentStacks.clear();
+}
+
+void V8DebuggerAgentImpl::setBlackboxPatterns(ErrorString* errorString, std::unique_ptr<protocol::Array<String16>> patterns)
+{
+ if (!patterns->length()) {
+ m_blackboxPattern = nullptr;
+ m_state->remove(DebuggerAgentState::blackboxPattern);
+ return;
+ }
+
+ String16Builder patternBuilder;
+ patternBuilder.append("(");
+ for (size_t i = 0; i < patterns->length() - 1; ++i)
+ patternBuilder.append(patterns->get(i) + "|");
+ patternBuilder.append(patterns->get(patterns->length() - 1) + ")");
+ String16 pattern = patternBuilder.toString();
+ if (!setBlackboxPattern(errorString, pattern))
+ return;
+ m_state->setString(DebuggerAgentState::blackboxPattern, pattern);
+}
+
+bool V8DebuggerAgentImpl::setBlackboxPattern(ErrorString* errorString, const String16& pattern)
+{
+ std::unique_ptr<V8Regex> regex = wrapUnique(new V8Regex(m_debugger, pattern, true /** caseSensitive */, false /** multiline */));
+ if (!regex->isValid()) {
+ *errorString = "Pattern parser error: " + regex->errorMessage();
+ return false;
+ }
+ m_blackboxPattern = std::move(regex);
+ return true;
+}
+
+void V8DebuggerAgentImpl::setBlackboxedRanges(ErrorString* error, const String16& scriptId, std::unique_ptr<protocol::Array<protocol::Debugger::ScriptPosition>> inPositions)
+{
+ if (!m_scripts.contains(scriptId)) {
+ *error = "No script with passed id.";
+ return;
+ }
+
+ if (!inPositions->length()) {
+ m_blackboxedPositions.remove(scriptId);
+ return;
+ }
+
+ protocol::Vector<std::pair<int, int>> positions(inPositions->length());
+ for (size_t i = 0; i < positions.size(); ++i) {
+ protocol::Debugger::ScriptPosition* position = inPositions->get(i);
+ if (position->getLine() < 0) {
+ *error = "Position missing 'line' or 'line' < 0.";
+ return;
+ }
+ if (position->getColumn() < 0) {
+ *error = "Position missing 'column' or 'column' < 0.";
+ return;
+ }
+ positions[i] = std::make_pair(position->getLine(), position->getColumn());
+ }
+
+ for (size_t i = 1; i < positions.size(); ++i) {
+ if (positions[i - 1].first < positions[i].first)
+ continue;
+ if (positions[i - 1].first == positions[i].first && positions[i - 1].second < positions[i].second)
+ continue;
+ *error = "Input positions array is not sorted or contains duplicate values.";
+ return;
+ }
+
+ m_blackboxedPositions.set(scriptId, positions);
+}
+
+void V8DebuggerAgentImpl::willExecuteScript(int scriptId)
+{
+ changeJavaScriptRecursionLevel(+1);
+ // Fast return.
+ if (m_scheduledDebuggerStep != StepInto)
+ return;
+ // Skip unknown scripts (e.g. InjectedScript).
+ if (!m_scripts.contains(String16::number(scriptId)))
+ return;
+ schedulePauseOnNextStatementIfSteppingInto();
+}
+
+void V8DebuggerAgentImpl::didExecuteScript()
+{
+ changeJavaScriptRecursionLevel(-1);
+}
+
+void V8DebuggerAgentImpl::changeJavaScriptRecursionLevel(int step)
+{
+ if (m_javaScriptPauseScheduled && !m_skipAllPauses && !debugger().isPaused()) {
+ // Do not ever loose user's pause request until we have actually paused.
+ debugger().setPauseOnNextStatement(true);
+ }
+ if (m_scheduledDebuggerStep == StepOut) {
+ m_recursionLevelForStepOut += step;
+ if (!m_recursionLevelForStepOut) {
+ // When StepOut crosses a task boundary (i.e. js -> blink_c++) from where it was requested,
+ // switch stepping to step into a next JS task, as if we exited to a blackboxed framework.
+ m_scheduledDebuggerStep = StepInto;
+ m_skipNextDebuggerStepOut = false;
+ }
+ }
+ if (m_recursionLevelForStepFrame) {
+ m_recursionLevelForStepFrame += step;
+ if (!m_recursionLevelForStepFrame) {
+ // We have walked through a blackboxed framework and got back to where we started.
+ // If there was no stepping scheduled, we should cancel the stepping explicitly,
+ // since there may be a scheduled StepFrame left.
+ // Otherwise, if we were stepping in/over, the StepFrame will stop at the right location,
+ // whereas if we were stepping out, we should continue doing so after debugger pauses
+ // from the old StepFrame.
+ m_skippedStepFrameCount = 0;
+ if (m_scheduledDebuggerStep == NoStep)
+ debugger().clearStepping();
+ else if (m_scheduledDebuggerStep == StepOut)
+ m_skipNextDebuggerStepOut = true;
+ }
+ }
+}
+
+std::unique_ptr<Array<CallFrame>> V8DebuggerAgentImpl::currentCallFrames(ErrorString* errorString)
+{
+ if (m_pausedContext.IsEmpty() || !m_pausedCallFrames.size())
+ return Array<CallFrame>::create();
+ ErrorString ignored;
+ InjectedScript* topFrameInjectedScript = m_session->findInjectedScript(&ignored, V8Debugger::contextId(m_pausedContext.Get(m_isolate)));
+ if (!topFrameInjectedScript) {
+ // Context has been reported as removed while on pause.
+ return Array<CallFrame>::create();
+ }
+
+ v8::HandleScope handles(m_isolate);
+ v8::Local<v8::Context> context = topFrameInjectedScript->context()->context();
+ v8::Context::Scope contextScope(context);
+
+ v8::Local<v8::Array> objects = v8::Array::New(m_isolate);
+ for (size_t frameOrdinal = 0; frameOrdinal < m_pausedCallFrames.size(); ++frameOrdinal) {
+ JavaScriptCallFrame* currentCallFrame = m_pausedCallFrames[frameOrdinal];
+
+ v8::Local<v8::Object> details = currentCallFrame->details();
+ if (hasInternalError(errorString, details.IsEmpty()))
+ return Array<CallFrame>::create();
+
+ int contextId = currentCallFrame->contextId();
+ InjectedScript* injectedScript = contextId ? m_session->findInjectedScript(&ignored, contextId) : nullptr;
+ if (!injectedScript)
+ injectedScript = topFrameInjectedScript;
+
+ String16 callFrameId = RemoteCallFrameId::serialize(injectedScript->context()->contextId(), frameOrdinal);
+ if (hasInternalError(errorString, !details->Set(context, toV8StringInternalized(m_isolate, "callFrameId"), toV8String(m_isolate, callFrameId)).FromMaybe(false)))
+ return Array<CallFrame>::create();
+
+ v8::Local<v8::Value> scopeChain;
+ if (hasInternalError(errorString, !details->Get(context, toV8StringInternalized(m_isolate, "scopeChain")).ToLocal(&scopeChain) || !scopeChain->IsArray()))
+ return Array<CallFrame>::create();
+ v8::Local<v8::Array> scopeChainArray = scopeChain.As<v8::Array>();
+ if (!injectedScript->wrapPropertyInArray(errorString, scopeChainArray, toV8StringInternalized(m_isolate, "object"), V8InspectorSession::backtraceObjectGroup))
+ return Array<CallFrame>::create();
+
+ if (!injectedScript->wrapObjectProperty(errorString, details, toV8StringInternalized(m_isolate, "this"), V8InspectorSession::backtraceObjectGroup))
+ return Array<CallFrame>::create();
+
+ if (details->Has(context, toV8StringInternalized(m_isolate, "returnValue")).FromMaybe(false)) {
+ if (!injectedScript->wrapObjectProperty(errorString, details, toV8StringInternalized(m_isolate, "returnValue"), V8InspectorSession::backtraceObjectGroup))
+ return Array<CallFrame>::create();
+ }
+
+ if (hasInternalError(errorString, !objects->Set(context, frameOrdinal, details).FromMaybe(false)))
+ return Array<CallFrame>::create();
+ }
+
+ protocol::ErrorSupport errorSupport;
+ std::unique_ptr<Array<CallFrame>> callFrames = Array<CallFrame>::parse(toProtocolValue(context, objects).get(), &errorSupport);
+ if (hasInternalError(errorString, !callFrames))
+ return Array<CallFrame>::create();
+ return callFrames;
+}
+
+std::unique_ptr<StackTrace> V8DebuggerAgentImpl::currentAsyncStackTrace()
+{
+ if (m_pausedContext.IsEmpty() || !m_maxAsyncCallStackDepth || !m_currentStacks.size() || !m_currentStacks.last())
+ return nullptr;
+
+ return m_currentStacks.last()->buildInspectorObjectForTail(this);
+}
+
+V8StackTraceImpl* V8DebuggerAgentImpl::currentAsyncCallChain()
+{
+ if (!m_currentStacks.size())
+ return nullptr;
+ return m_currentStacks.last();
+}
+
+void V8DebuggerAgentImpl::didParseSource(const V8DebuggerParsedScript& parsedScript)
+{
+ V8DebuggerScript script = parsedScript.script;
+
+ bool isDeprecatedSourceURL = false;
+ if (!parsedScript.success)
+ script.setSourceURL(V8ContentSearchUtil::findSourceURL(script.source(), false, &isDeprecatedSourceURL));
+ else if (script.hasSourceURL())
+ V8ContentSearchUtil::findSourceURL(script.source(), false, &isDeprecatedSourceURL);
+
+ bool isDeprecatedSourceMappingURL = false;
+ if (!parsedScript.success)
+ script.setSourceMappingURL(V8ContentSearchUtil::findSourceMapURL(script.source(), false, &isDeprecatedSourceMappingURL));
+ else if (!script.sourceMappingURL().isEmpty())
+ V8ContentSearchUtil::findSourceMapURL(script.source(), false, &isDeprecatedSourceMappingURL);
+
+ script.setHash(calculateHash(script.source()));
+
+ int executionContextId = script.executionContextId();
+ bool isContentScript = script.isContentScript();
+ bool isInternalScript = script.isInternalScript();
+ bool isLiveEdit = script.isLiveEdit();
+ bool hasSourceURL = script.hasSourceURL();
+ String16 scriptURL = script.sourceURL();
+ String16 sourceMapURL = script.sourceMappingURL();
+ bool deprecatedCommentWasUsed = isDeprecatedSourceURL || isDeprecatedSourceMappingURL;
+
+ const Maybe<String16>& sourceMapURLParam = sourceMapURL;
+ const bool* isContentScriptParam = isContentScript ? &isContentScript : nullptr;
+ const bool* isInternalScriptParam = isInternalScript ? &isInternalScript : nullptr;
+ const bool* isLiveEditParam = isLiveEdit ? &isLiveEdit : nullptr;
+ const bool* hasSourceURLParam = hasSourceURL ? &hasSourceURL : nullptr;
+ const bool* deprecatedCommentWasUsedParam = deprecatedCommentWasUsed ? &deprecatedCommentWasUsed : nullptr;
+ if (parsedScript.success)
+ m_frontend->scriptParsed(parsedScript.scriptId, scriptURL, script.startLine(), script.startColumn(), script.endLine(), script.endColumn(), executionContextId, script.hash(), isContentScriptParam, isInternalScriptParam, isLiveEditParam, sourceMapURLParam, hasSourceURLParam, deprecatedCommentWasUsedParam);
+ else
+ m_frontend->scriptFailedToParse(parsedScript.scriptId, scriptURL, script.startLine(), script.startColumn(), script.endLine(), script.endColumn(), executionContextId, script.hash(), isContentScriptParam, isInternalScriptParam, sourceMapURLParam, hasSourceURLParam, deprecatedCommentWasUsedParam);
+
+ m_scripts.set(parsedScript.scriptId, script);
+
+ if (scriptURL.isEmpty() || !parsedScript.success)
+ return;
+
+ protocol::DictionaryValue* breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints);
+ if (!breakpointsCookie)
+ return;
+
+ for (size_t i = 0; i < breakpointsCookie->size(); ++i) {
+ auto cookie = breakpointsCookie->at(i);
+ protocol::DictionaryValue* breakpointObject = protocol::DictionaryValue::cast(cookie.second);
+ bool isRegex;
+ breakpointObject->getBoolean(DebuggerAgentState::isRegex, &isRegex);
+ String16 url;
+ breakpointObject->getString(DebuggerAgentState::url, &url);
+ if (!matches(m_debugger, scriptURL, url, isRegex))
+ continue;
+ ScriptBreakpoint breakpoint;
+ breakpointObject->getNumber(DebuggerAgentState::lineNumber, &breakpoint.lineNumber);
+ breakpointObject->getNumber(DebuggerAgentState::columnNumber, &breakpoint.columnNumber);
+ breakpointObject->getString(DebuggerAgentState::condition, &breakpoint.condition);
+ std::unique_ptr<protocol::Debugger::Location> location = resolveBreakpoint(cookie.first, parsedScript.scriptId, breakpoint, UserBreakpointSource);
+ if (location)
+ m_frontend->breakpointResolved(cookie.first, std::move(location));
+ }
+}
+
+V8DebuggerAgentImpl::SkipPauseRequest V8DebuggerAgentImpl::didPause(v8::Local<v8::Context> context, v8::Local<v8::Value> exception, const protocol::Vector<String16>& hitBreakpoints, bool isPromiseRejection)
+{
+ JavaScriptCallFrames callFrames = debugger().currentCallFrames(1);
+ JavaScriptCallFrame* topCallFrame = callFrames.size() > 0 ? callFrames[0] : nullptr;
+
+ V8DebuggerAgentImpl::SkipPauseRequest result;
+ if (m_skipAllPauses)
+ result = RequestContinue;
+ else if (!hitBreakpoints.isEmpty())
+ result = RequestNoSkip; // Don't skip explicit breakpoints even if set in frameworks.
+ else if (!exception.IsEmpty())
+ result = shouldSkipExceptionPause(topCallFrame);
+ else if (m_scheduledDebuggerStep != NoStep || m_javaScriptPauseScheduled || m_pausingOnNativeEvent)
+ result = shouldSkipStepPause(topCallFrame);
+ else
+ result = RequestNoSkip;
+
+ m_skipNextDebuggerStepOut = false;
+ if (result != RequestNoSkip)
+ return result;
+ // Skip pauses inside V8 internal scripts and on syntax errors.
+ if (!topCallFrame)
+ return RequestContinue;
+
+ DCHECK(m_pausedContext.IsEmpty());
+ m_pausedCallFrames.swap(debugger().currentCallFrames());
+ m_pausedContext.Reset(m_isolate, context);
+ v8::HandleScope handles(m_isolate);
+
+ if (!exception.IsEmpty()) {
+ ErrorString ignored;
+ InjectedScript* injectedScript = m_session->findInjectedScript(&ignored, V8Debugger::contextId(context));
+ if (injectedScript) {
+ m_breakReason = isPromiseRejection ? protocol::Debugger::Paused::ReasonEnum::PromiseRejection : protocol::Debugger::Paused::ReasonEnum::Exception;
+ ErrorString errorString;
+ auto obj = injectedScript->wrapObject(&errorString, exception, V8InspectorSession::backtraceObjectGroup);
+ m_breakAuxData = obj ? obj->serialize() : nullptr;
+ // m_breakAuxData might be null after this.
+ }
+ }
+
+ std::unique_ptr<Array<String16>> hitBreakpointIds = Array<String16>::create();
+
+ for (const auto& point : hitBreakpoints) {
+ DebugServerBreakpointToBreakpointIdAndSourceMap::iterator breakpointIterator = m_serverBreakpoints.find(point);
+ if (breakpointIterator != m_serverBreakpoints.end()) {
+ const String16& localId = breakpointIterator->second->first;
+ hitBreakpointIds->addItem(localId);
+
+ BreakpointSource source = breakpointIterator->second->second;
+ if (m_breakReason == protocol::Debugger::Paused::ReasonEnum::Other && source == DebugCommandBreakpointSource)
+ m_breakReason = protocol::Debugger::Paused::ReasonEnum::DebugCommand;
+ }
+ }
+
+ ErrorString errorString;
+ m_frontend->paused(currentCallFrames(&errorString), m_breakReason, std::move(m_breakAuxData), std::move(hitBreakpointIds), currentAsyncStackTrace());
+ m_scheduledDebuggerStep = NoStep;
+ m_javaScriptPauseScheduled = false;
+ m_steppingFromFramework = false;
+ m_pausingOnNativeEvent = false;
+ m_skippedStepFrameCount = 0;
+ m_recursionLevelForStepFrame = 0;
+
+ if (!m_continueToLocationBreakpointId.isEmpty()) {
+ debugger().removeBreakpoint(m_continueToLocationBreakpointId);
+ m_continueToLocationBreakpointId = "";
+ }
+ return result;
+}
+
+void V8DebuggerAgentImpl::didContinue()
+{
+ m_pausedContext.Reset();
+ JavaScriptCallFrames emptyCallFrames;
+ m_pausedCallFrames.swap(emptyCallFrames);
+ clearBreakDetails();
+ m_frontend->resumed();
+}
+
+void V8DebuggerAgentImpl::breakProgram(const String16& breakReason, std::unique_ptr<protocol::DictionaryValue> data)
+{
+ if (!enabled() || m_skipAllPauses || !m_pausedContext.IsEmpty() || isCurrentCallStackEmptyOrBlackboxed() || !debugger().breakpointsActivated())
+ return;
+ m_breakReason = breakReason;
+ m_breakAuxData = std::move(data);
+ m_scheduledDebuggerStep = NoStep;
+ m_steppingFromFramework = false;
+ m_pausingOnNativeEvent = false;
+ debugger().breakProgram();
+}
+
+void V8DebuggerAgentImpl::breakProgramOnException(const String16& breakReason, std::unique_ptr<protocol::DictionaryValue> data)
+{
+ if (!enabled() || m_debugger->getPauseOnExceptionsState() == V8DebuggerImpl::DontPauseOnExceptions)
+ return;
+ breakProgram(breakReason, std::move(data));
+}
+
+bool V8DebuggerAgentImpl::assertPaused(ErrorString* errorString)
+{
+ if (m_pausedContext.IsEmpty()) {
+ *errorString = "Can only perform operation while paused.";
+ return false;
+ }
+ return true;
+}
+
+void V8DebuggerAgentImpl::clearBreakDetails()
+{
+ m_breakReason = protocol::Debugger::Paused::ReasonEnum::Other;
+ m_breakAuxData = nullptr;
+}
+
+void V8DebuggerAgentImpl::setBreakpointAt(const String16& scriptId, int lineNumber, int columnNumber, BreakpointSource source, const String16& condition)
+{
+ String16 breakpointId = generateBreakpointId(scriptId, lineNumber, columnNumber, source);
+ ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition);
+ resolveBreakpoint(breakpointId, scriptId, breakpoint, source);
+}
+
+void V8DebuggerAgentImpl::removeBreakpointAt(const String16& scriptId, int lineNumber, int columnNumber, BreakpointSource source)
+{
+ removeBreakpoint(generateBreakpointId(scriptId, lineNumber, columnNumber, source));
+}
+
+void V8DebuggerAgentImpl::reset()
+{
+ if (!enabled())
+ return;
+ m_scheduledDebuggerStep = NoStep;
+ m_scripts.clear();
+ m_blackboxedPositions.clear();
+ m_breakpointIdToDebuggerBreakpointIds.clear();
+ allAsyncTasksCanceled();
+}
+
+} // namespace blink
diff --git a/deps/v8_inspector/platform/v8_inspector/V8DebuggerAgentImpl.h b/deps/v8_inspector/platform/v8_inspector/V8DebuggerAgentImpl.h
new file mode 100644
index 0000000000..a2651970b7
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8DebuggerAgentImpl.h
@@ -0,0 +1,248 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8DebuggerAgentImpl_h
+#define V8DebuggerAgentImpl_h
+
+#include "platform/inspector_protocol/Collections.h"
+#include "platform/inspector_protocol/Dispatcher.h"
+#include "platform/inspector_protocol/Frontend.h"
+#include "platform/inspector_protocol/String16.h"
+#include "platform/v8_inspector/V8DebuggerImpl.h"
+#include "platform/v8_inspector/public/V8DebuggerAgent.h"
+
+namespace blink {
+
+class JavaScriptCallFrame;
+class PromiseTracker;
+class V8InspectorSessionImpl;
+class V8Regex;
+class V8StackTraceImpl;
+
+namespace protocol {
+class DictionaryValue;
+}
+
+using protocol::Maybe;
+
+class V8DebuggerAgentImpl : public V8DebuggerAgent {
+ PROTOCOL_DISALLOW_COPY(V8DebuggerAgentImpl);
+public:
+ enum SkipPauseRequest {
+ RequestNoSkip,
+ RequestContinue,
+ RequestStepInto,
+ RequestStepOut,
+ RequestStepFrame
+ };
+
+ enum BreakpointSource {
+ UserBreakpointSource,
+ DebugCommandBreakpointSource,
+ MonitorCommandBreakpointSource
+ };
+
+ explicit V8DebuggerAgentImpl(V8InspectorSessionImpl*);
+ ~V8DebuggerAgentImpl() override;
+
+ void setInspectorState(protocol::DictionaryValue*) override;
+ void setFrontend(protocol::Frontend::Debugger* frontend) override { m_frontend = frontend; }
+ void clearFrontend() override;
+ void restore() override;
+ void disable(ErrorString*) override;
+
+ // Part of the protocol.
+ void enable(ErrorString*) override;
+ void setBreakpointsActive(ErrorString*, bool active) override;
+ void setSkipAllPauses(ErrorString*, bool skipped) override;
+ void setBreakpointByUrl(ErrorString*,
+ int lineNumber,
+ const Maybe<String16>& optionalURL,
+ const Maybe<String16>& optionalURLRegex,
+ const Maybe<int>& optionalColumnNumber,
+ const Maybe<String16>& optionalCondition,
+ String16*,
+ std::unique_ptr<protocol::Array<protocol::Debugger::Location>>* locations) override;
+ void setBreakpoint(ErrorString*,
+ std::unique_ptr<protocol::Debugger::Location>,
+ const Maybe<String16>& optionalCondition,
+ String16*,
+ std::unique_ptr<protocol::Debugger::Location>* actualLocation) override;
+ void removeBreakpoint(ErrorString*, const String16& breakpointId) override;
+ void continueToLocation(ErrorString*,
+ std::unique_ptr<protocol::Debugger::Location>,
+ const Maybe<bool>& interstateLocationOpt) override;
+ void getBacktrace(ErrorString*,
+ std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>*,
+ Maybe<protocol::Runtime::StackTrace>*) override;
+ void searchInContent(ErrorString*,
+ const String16& scriptId,
+ const String16& query,
+ const Maybe<bool>& optionalCaseSensitive,
+ const Maybe<bool>& optionalIsRegex,
+ std::unique_ptr<protocol::Array<protocol::Debugger::SearchMatch>>*) override;
+ void canSetScriptSource(ErrorString*, bool* result) override { *result = true; }
+ void setScriptSource(ErrorString*,
+ const String16& inScriptId,
+ const String16& inScriptSource,
+ const Maybe<bool>& inPreview,
+ Maybe<protocol::Array<protocol::Debugger::CallFrame>>* optOutCallFrames,
+ Maybe<bool>* optOutStackChanged,
+ Maybe<protocol::Runtime::StackTrace>* optOutAsyncStackTrace,
+ Maybe<protocol::Debugger::SetScriptSourceError>* optOutCompileError) override;
+ void restartFrame(ErrorString*,
+ const String16& callFrameId,
+ std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>* newCallFrames,
+ Maybe<protocol::Runtime::StackTrace>* asyncStackTrace) override;
+ void getScriptSource(ErrorString*, const String16& scriptId, String16* scriptSource) override;
+ void getFunctionDetails(ErrorString*,
+ const String16& functionId,
+ std::unique_ptr<protocol::Debugger::FunctionDetails>*) override;
+ void getGeneratorObjectDetails(ErrorString*,
+ const String16& objectId,
+ std::unique_ptr<protocol::Debugger::GeneratorObjectDetails>*) override;
+ void getCollectionEntries(ErrorString*,
+ const String16& objectId,
+ std::unique_ptr<protocol::Array<protocol::Debugger::CollectionEntry>>*) override;
+ void pause(ErrorString*) override;
+ void resume(ErrorString*) override;
+ void stepOver(ErrorString*) override;
+ void stepInto(ErrorString*) override;
+ void stepOut(ErrorString*) override;
+ void setPauseOnExceptions(ErrorString*, const String16& pauseState) override;
+ void evaluateOnCallFrame(ErrorString*,
+ const String16& callFrameId,
+ const String16& expression,
+ const Maybe<String16>& objectGroup,
+ const Maybe<bool>& includeCommandLineAPI,
+ const Maybe<bool>& doNotPauseOnExceptionsAndMuteConsole,
+ const Maybe<bool>& returnByValue,
+ const Maybe<bool>& generatePreview,
+ std::unique_ptr<protocol::Runtime::RemoteObject>* result,
+ Maybe<bool>* wasThrown,
+ Maybe<protocol::Runtime::ExceptionDetails>*) override;
+ void setVariableValue(ErrorString*,
+ int scopeNumber,
+ const String16& variableName,
+ std::unique_ptr<protocol::Runtime::CallArgument> newValue,
+ const String16& callFrame) override;
+ void setAsyncCallStackDepth(ErrorString*, int depth) override;
+ void setBlackboxPatterns(ErrorString*,
+ std::unique_ptr<protocol::Array<String16>> patterns) override;
+ void setBlackboxedRanges(ErrorString*,
+ const String16& scriptId,
+ std::unique_ptr<protocol::Array<protocol::Debugger::ScriptPosition>> positions) override;
+
+ bool enabled();
+ V8DebuggerImpl& debugger() { return *m_debugger; }
+
+ void setBreakpointAt(const String16& scriptId, int lineNumber, int columnNumber, BreakpointSource, const String16& condition = String16());
+ void removeBreakpointAt(const String16& scriptId, int lineNumber, int columnNumber, BreakpointSource);
+ void schedulePauseOnNextStatement(const String16& breakReason, std::unique_ptr<protocol::DictionaryValue> data);
+ void cancelPauseOnNextStatement();
+ void breakProgram(const String16& breakReason, std::unique_ptr<protocol::DictionaryValue> data);
+ void breakProgramOnException(const String16& breakReason, std::unique_ptr<protocol::DictionaryValue> data);
+
+ // Async call stacks implementation.
+ void asyncTaskScheduled(const String16& taskName, void* task, bool recurring);
+ void asyncTaskCanceled(void* task);
+ void asyncTaskStarted(void* task);
+ void asyncTaskFinished(void* task);
+ void allAsyncTasksCanceled();
+
+ void reset();
+
+ // Interface for V8DebuggerImpl
+ SkipPauseRequest didPause(v8::Local<v8::Context>, v8::Local<v8::Value> exception, const protocol::Vector<String16>& hitBreakpoints, bool isPromiseRejection);
+ void didContinue();
+ void didParseSource(const V8DebuggerParsedScript&);
+ bool v8AsyncTaskEventsEnabled() const;
+ void didReceiveV8AsyncTaskEvent(v8::Local<v8::Context>, const String16& eventType, const String16& eventName, int id);
+ void willExecuteScript(int scriptId);
+ void didExecuteScript();
+
+ v8::Isolate* isolate() { return m_isolate; }
+ int maxAsyncCallChainDepth() { return m_maxAsyncCallStackDepth; }
+ V8StackTraceImpl* currentAsyncCallChain();
+
+private:
+ bool checkEnabled(ErrorString*);
+ void enable();
+
+ SkipPauseRequest shouldSkipExceptionPause(JavaScriptCallFrame* topCallFrame);
+ SkipPauseRequest shouldSkipStepPause(JavaScriptCallFrame* topCallFrame);
+
+ void schedulePauseOnNextStatementIfSteppingInto();
+
+ std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>> currentCallFrames(ErrorString*);
+ std::unique_ptr<protocol::Runtime::StackTrace> currentAsyncStackTrace();
+
+ void changeJavaScriptRecursionLevel(int step);
+
+ void setPauseOnExceptionsImpl(ErrorString*, int);
+
+ std::unique_ptr<protocol::Debugger::Location> resolveBreakpoint(const String16& breakpointId, const String16& scriptId, const ScriptBreakpoint&, BreakpointSource);
+ void removeBreakpoint(const String16& breakpointId);
+ bool assertPaused(ErrorString*);
+ void clearBreakDetails();
+
+ bool isCurrentCallStackEmptyOrBlackboxed();
+ bool isTopPausedCallFrameBlackboxed();
+ bool isCallFrameWithUnknownScriptOrBlackboxed(JavaScriptCallFrame*);
+
+ void internalSetAsyncCallStackDepth(int);
+ void increaseCachedSkipStackGeneration();
+
+ bool setBlackboxPattern(ErrorString*, const String16& pattern);
+
+ using ScriptsMap = protocol::HashMap<String16, V8DebuggerScript>;
+ using BreakpointIdToDebuggerBreakpointIdsMap = protocol::HashMap<String16, protocol::Vector<String16>>;
+ using DebugServerBreakpointToBreakpointIdAndSourceMap = protocol::HashMap<String16, std::pair<String16, BreakpointSource>>;
+ using MuteBreakpoins = protocol::HashMap<String16, std::pair<String16, int>>;
+
+ enum DebuggerStep {
+ NoStep = 0,
+ StepInto,
+ StepOver,
+ StepOut
+ };
+
+ V8DebuggerImpl* m_debugger;
+ V8InspectorSessionImpl* m_session;
+ bool m_enabled;
+ protocol::DictionaryValue* m_state;
+ protocol::Frontend::Debugger* m_frontend;
+ v8::Isolate* m_isolate;
+ v8::Global<v8::Context> m_pausedContext;
+ JavaScriptCallFrames m_pausedCallFrames;
+ ScriptsMap m_scripts;
+ BreakpointIdToDebuggerBreakpointIdsMap m_breakpointIdToDebuggerBreakpointIds;
+ DebugServerBreakpointToBreakpointIdAndSourceMap m_serverBreakpoints;
+ String16 m_continueToLocationBreakpointId;
+ String16 m_breakReason;
+ std::unique_ptr<protocol::DictionaryValue> m_breakAuxData;
+ DebuggerStep m_scheduledDebuggerStep;
+ bool m_skipNextDebuggerStepOut;
+ bool m_javaScriptPauseScheduled;
+ bool m_steppingFromFramework;
+ bool m_pausingOnNativeEvent;
+
+ int m_skippedStepFrameCount;
+ int m_recursionLevelForStepOut;
+ int m_recursionLevelForStepFrame;
+ bool m_skipAllPauses;
+
+ using AsyncTaskToStackTrace = protocol::HashMap<void*, std::unique_ptr<V8StackTraceImpl>>;
+ AsyncTaskToStackTrace m_asyncTaskStacks;
+ protocol::HashSet<void*> m_recurringTasks;
+ int m_maxAsyncCallStackDepth;
+ protocol::Vector<std::unique_ptr<V8StackTraceImpl>> m_currentStacks;
+ std::unique_ptr<V8Regex> m_blackboxPattern;
+ protocol::HashMap<String16, protocol::Vector<std::pair<int, int>>> m_blackboxedPositions;
+};
+
+} // namespace blink
+
+
+#endif // V8DebuggerAgentImpl_h
diff --git a/deps/v8_inspector/platform/v8_inspector/V8DebuggerImpl.cpp b/deps/v8_inspector/platform/v8_inspector/V8DebuggerImpl.cpp
new file mode 100644
index 0000000000..6cb4371ede
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8DebuggerImpl.cpp
@@ -0,0 +1,854 @@
+/*
+ * Copyright (c) 2010-2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "platform/v8_inspector/V8DebuggerImpl.h"
+
+#include "platform/inspector_protocol/Values.h"
+#include "platform/v8_inspector/Atomics.h"
+#include "platform/v8_inspector/DebuggerScript.h"
+#include "platform/v8_inspector/InspectedContext.h"
+#include "platform/v8_inspector/ScriptBreakpoint.h"
+#include "platform/v8_inspector/V8Compat.h"
+#include "platform/v8_inspector/V8DebuggerAgentImpl.h"
+#include "platform/v8_inspector/V8InspectorSessionImpl.h"
+#include "platform/v8_inspector/V8RuntimeAgentImpl.h"
+#include "platform/v8_inspector/V8StackTraceImpl.h"
+#include "platform/v8_inspector/V8StringUtil.h"
+#include "platform/v8_inspector/public/V8DebuggerClient.h"
+#include <v8-profiler.h>
+
+namespace blink {
+
+namespace {
+const char stepIntoV8MethodName[] = "stepIntoStatement";
+const char stepOutV8MethodName[] = "stepOutOfFunction";
+volatile int s_lastContextId = 0;
+
+inline v8::Local<v8::Boolean> v8Boolean(bool value, v8::Isolate* isolate)
+{
+ return value ? v8::True(isolate) : v8::False(isolate);
+}
+
+}
+
+static bool inLiveEditScope = false;
+
+v8::MaybeLocal<v8::Value> V8DebuggerImpl::callDebuggerMethod(const char* functionName, int argc, v8::Local<v8::Value> argv[])
+{
+ v8::MicrotasksScope microtasks(m_isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
+ v8::Local<v8::Object> debuggerScript = m_debuggerScript.Get(m_isolate);
+ v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(debuggerScript->Get(v8InternalizedString(functionName)));
+ DCHECK(m_isolate->InContext());
+ return function->Call(m_isolate->GetCurrentContext(), debuggerScript, argc, argv);
+}
+
+std::unique_ptr<V8Debugger> V8Debugger::create(v8::Isolate* isolate, V8DebuggerClient* client)
+{
+ return wrapUnique(new V8DebuggerImpl(isolate, client));
+}
+
+V8DebuggerImpl::V8DebuggerImpl(v8::Isolate* isolate, V8DebuggerClient* client)
+ : m_isolate(isolate)
+ , m_client(client)
+ , m_enabledAgentsCount(0)
+ , m_breakpointsActivated(true)
+ , m_runningNestedMessageLoop(false)
+{
+}
+
+V8DebuggerImpl::~V8DebuggerImpl()
+{
+}
+
+void V8DebuggerImpl::enable()
+{
+ DCHECK(!enabled());
+ v8::HandleScope scope(m_isolate);
+ v8::Debug::SetDebugEventListener(m_isolate, &V8DebuggerImpl::v8DebugEventCallback, v8::External::New(m_isolate, this));
+ m_debuggerContext.Reset(m_isolate, v8::Debug::GetDebugContext(m_isolate));
+ compileDebuggerScript();
+}
+
+void V8DebuggerImpl::disable()
+{
+ DCHECK(enabled());
+ clearBreakpoints();
+ m_debuggerScript.Reset();
+ m_debuggerContext.Reset();
+ v8::Debug::SetDebugEventListener(m_isolate, nullptr);
+}
+
+bool V8DebuggerImpl::enabled() const
+{
+ return !m_debuggerScript.IsEmpty();
+}
+
+int V8Debugger::contextId(v8::Local<v8::Context> context)
+{
+ v8::Local<v8::Value> data = context->GetEmbedderData(static_cast<int>(v8::Context::kDebugIdIndex));
+ if (data.IsEmpty() || !data->IsString())
+ return 0;
+ String16 dataString = toProtocolString(data.As<v8::String>());
+ if (dataString.isEmpty())
+ return 0;
+ size_t commaPos = dataString.find(",");
+ if (commaPos == kNotFound)
+ return 0;
+ size_t commaPos2 = dataString.find(",", commaPos + 1);
+ if (commaPos2 == kNotFound)
+ return 0;
+ return dataString.substring(commaPos + 1, commaPos2 - commaPos - 1).toInt();
+}
+
+static int getGroupId(v8::Local<v8::Context> context)
+{
+ v8::Local<v8::Value> data = context->GetEmbedderData(static_cast<int>(v8::Context::kDebugIdIndex));
+ if (data.IsEmpty() || !data->IsString())
+ return 0;
+ String16 dataString = toProtocolString(data.As<v8::String>());
+ if (dataString.isEmpty())
+ return 0;
+ size_t commaPos = dataString.find(",");
+ if (commaPos == kNotFound)
+ return 0;
+ return dataString.substring(0, commaPos).toInt();
+}
+
+void V8DebuggerImpl::debuggerAgentEnabled()
+{
+ if (!m_enabledAgentsCount++)
+ enable();
+}
+
+void V8DebuggerImpl::debuggerAgentDisabled()
+{
+ if (!--m_enabledAgentsCount)
+ disable();
+}
+
+V8DebuggerAgentImpl* V8DebuggerImpl::findEnabledDebuggerAgent(int contextGroupId)
+{
+ if (!contextGroupId)
+ return nullptr;
+ V8InspectorSessionImpl* session = m_sessions.get(contextGroupId);
+ if (session && session->debuggerAgentImpl()->enabled())
+ return session->debuggerAgentImpl();
+ return nullptr;
+}
+
+V8DebuggerAgentImpl* V8DebuggerImpl::findEnabledDebuggerAgent(v8::Local<v8::Context> context)
+{
+ return findEnabledDebuggerAgent(getGroupId(context));
+}
+
+void V8DebuggerImpl::getCompiledScripts(int contextGroupId, protocol::Vector<V8DebuggerParsedScript>& result)
+{
+ v8::HandleScope scope(m_isolate);
+ v8::MicrotasksScope microtasks(m_isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
+ v8::Local<v8::Object> debuggerScript = m_debuggerScript.Get(m_isolate);
+ DCHECK(!debuggerScript->IsUndefined());
+ v8::Local<v8::Function> getScriptsFunction = v8::Local<v8::Function>::Cast(debuggerScript->Get(v8InternalizedString("getScripts")));
+ v8::Local<v8::Value> argv[] = { v8::Integer::New(m_isolate, contextGroupId) };
+ v8::Local<v8::Value> value;
+ if (!getScriptsFunction->Call(debuggerContext(), debuggerScript, PROTOCOL_ARRAY_LENGTH(argv), argv).ToLocal(&value))
+ return;
+ DCHECK(value->IsArray());
+ v8::Local<v8::Array> scriptsArray = v8::Local<v8::Array>::Cast(value);
+ result.resize(scriptsArray->Length());
+ for (unsigned i = 0; i < scriptsArray->Length(); ++i)
+ result[i] = createParsedScript(v8::Local<v8::Object>::Cast(scriptsArray->Get(v8::Integer::New(m_isolate, i))), true);
+}
+
+String16 V8DebuggerImpl::setBreakpoint(const String16& sourceID, const ScriptBreakpoint& scriptBreakpoint, int* actualLineNumber, int* actualColumnNumber, bool interstatementLocation)
+{
+ v8::HandleScope scope(m_isolate);
+ v8::Context::Scope contextScope(debuggerContext());
+
+ v8::Local<v8::Object> info = v8::Object::New(m_isolate);
+ info->Set(v8InternalizedString("sourceID"), toV8String(m_isolate, sourceID));
+ info->Set(v8InternalizedString("lineNumber"), v8::Integer::New(m_isolate, scriptBreakpoint.lineNumber));
+ info->Set(v8InternalizedString("columnNumber"), v8::Integer::New(m_isolate, scriptBreakpoint.columnNumber));
+ info->Set(v8InternalizedString("interstatementLocation"), v8Boolean(interstatementLocation, m_isolate));
+ info->Set(v8InternalizedString("condition"), toV8String(m_isolate, scriptBreakpoint.condition));
+
+ v8::Local<v8::Function> setBreakpointFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.Get(m_isolate)->Get(v8InternalizedString("setBreakpoint")));
+ v8::Local<v8::Value> breakpointId = v8::Debug::Call(debuggerContext(), setBreakpointFunction, info).ToLocalChecked();
+ if (!breakpointId->IsString())
+ return "";
+ *actualLineNumber = info->Get(v8InternalizedString("lineNumber"))->Int32Value();
+ *actualColumnNumber = info->Get(v8InternalizedString("columnNumber"))->Int32Value();
+ return toProtocolString(breakpointId.As<v8::String>());
+}
+
+void V8DebuggerImpl::removeBreakpoint(const String16& breakpointId)
+{
+ v8::HandleScope scope(m_isolate);
+ v8::Context::Scope contextScope(debuggerContext());
+
+ v8::Local<v8::Object> info = v8::Object::New(m_isolate);
+ info->Set(v8InternalizedString("breakpointId"), toV8String(m_isolate, breakpointId));
+
+ v8::Local<v8::Function> removeBreakpointFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.Get(m_isolate)->Get(v8InternalizedString("removeBreakpoint")));
+ v8::Debug::Call(debuggerContext(), removeBreakpointFunction, info).ToLocalChecked();
+}
+
+void V8DebuggerImpl::clearBreakpoints()
+{
+ v8::HandleScope scope(m_isolate);
+ v8::Context::Scope contextScope(debuggerContext());
+
+ v8::Local<v8::Function> clearBreakpoints = v8::Local<v8::Function>::Cast(m_debuggerScript.Get(m_isolate)->Get(v8InternalizedString("clearBreakpoints")));
+ v8::Debug::Call(debuggerContext(), clearBreakpoints).ToLocalChecked();
+}
+
+void V8DebuggerImpl::setBreakpointsActivated(bool activated)
+{
+ if (!enabled()) {
+ NOTREACHED();
+ return;
+ }
+ v8::HandleScope scope(m_isolate);
+ v8::Context::Scope contextScope(debuggerContext());
+
+ v8::Local<v8::Object> info = v8::Object::New(m_isolate);
+ info->Set(v8InternalizedString("enabled"), v8::Boolean::New(m_isolate, activated));
+ v8::Local<v8::Function> setBreakpointsActivated = v8::Local<v8::Function>::Cast(m_debuggerScript.Get(m_isolate)->Get(v8InternalizedString("setBreakpointsActivated")));
+ v8::Debug::Call(debuggerContext(), setBreakpointsActivated, info).ToLocalChecked();
+
+ m_breakpointsActivated = activated;
+}
+
+V8DebuggerImpl::PauseOnExceptionsState V8DebuggerImpl::getPauseOnExceptionsState()
+{
+ DCHECK(enabled());
+ v8::HandleScope scope(m_isolate);
+ v8::Context::Scope contextScope(debuggerContext());
+
+ v8::Local<v8::Value> argv[] = { v8::Undefined(m_isolate) };
+ v8::Local<v8::Value> result = callDebuggerMethod("pauseOnExceptionsState", 0, argv).ToLocalChecked();
+ return static_cast<V8DebuggerImpl::PauseOnExceptionsState>(result->Int32Value());
+}
+
+void V8DebuggerImpl::setPauseOnExceptionsState(PauseOnExceptionsState pauseOnExceptionsState)
+{
+ DCHECK(enabled());
+ v8::HandleScope scope(m_isolate);
+ v8::Context::Scope contextScope(debuggerContext());
+
+ v8::Local<v8::Value> argv[] = { v8::Int32::New(m_isolate, pauseOnExceptionsState) };
+ callDebuggerMethod("setPauseOnExceptionsState", 1, argv);
+}
+
+void V8DebuggerImpl::setPauseOnNextStatement(bool pause)
+{
+ if (m_runningNestedMessageLoop)
+ return;
+ if (pause)
+ v8::Debug::DebugBreak(m_isolate);
+ else
+ v8::Debug::CancelDebugBreak(m_isolate);
+}
+
+bool V8DebuggerImpl::canBreakProgram()
+{
+ if (!m_breakpointsActivated)
+ return false;
+ return m_isolate->InContext();
+}
+
+void V8DebuggerImpl::breakProgram()
+{
+ if (isPaused()) {
+ DCHECK(!m_runningNestedMessageLoop);
+ v8::Local<v8::Value> exception;
+ v8::Local<v8::Array> hitBreakpoints;
+ handleProgramBreak(m_pausedContext, m_executionState, exception, hitBreakpoints);
+ return;
+ }
+
+ if (!canBreakProgram())
+ return;
+
+ v8::HandleScope scope(m_isolate);
+ v8::Local<v8::Function> breakFunction;
+ if (!v8::Function::New(m_isolate->GetCurrentContext(), &V8DebuggerImpl::breakProgramCallback, v8::External::New(m_isolate, this)).ToLocal(&breakFunction))
+ return;
+ v8::Debug::Call(debuggerContext(), breakFunction).ToLocalChecked();
+}
+
+void V8DebuggerImpl::continueProgram()
+{
+ if (isPaused())
+ m_client->quitMessageLoopOnPause();
+ m_pausedContext.Clear();
+ m_executionState.Clear();
+}
+
+void V8DebuggerImpl::stepIntoStatement()
+{
+ DCHECK(isPaused());
+ DCHECK(!m_executionState.IsEmpty());
+ v8::HandleScope handleScope(m_isolate);
+ v8::Local<v8::Value> argv[] = { m_executionState };
+ callDebuggerMethod(stepIntoV8MethodName, 1, argv);
+ continueProgram();
+}
+
+void V8DebuggerImpl::stepOverStatement()
+{
+ DCHECK(isPaused());
+ DCHECK(!m_executionState.IsEmpty());
+ v8::HandleScope handleScope(m_isolate);
+ v8::Local<v8::Value> argv[] = { m_executionState };
+ callDebuggerMethod("stepOverStatement", 1, argv);
+ continueProgram();
+}
+
+void V8DebuggerImpl::stepOutOfFunction()
+{
+ DCHECK(isPaused());
+ DCHECK(!m_executionState.IsEmpty());
+ v8::HandleScope handleScope(m_isolate);
+ v8::Local<v8::Value> argv[] = { m_executionState };
+ callDebuggerMethod(stepOutV8MethodName, 1, argv);
+ continueProgram();
+}
+
+void V8DebuggerImpl::clearStepping()
+{
+ DCHECK(enabled());
+ v8::HandleScope scope(m_isolate);
+ v8::Context::Scope contextScope(debuggerContext());
+
+ v8::Local<v8::Value> argv[] = { v8::Undefined(m_isolate) };
+ callDebuggerMethod("clearStepping", 0, argv);
+}
+
+bool V8DebuggerImpl::setScriptSource(const String16& sourceID, const String16& newContent, bool preview, ErrorString* error, Maybe<protocol::Debugger::SetScriptSourceError>* errorData, JavaScriptCallFrames* newCallFrames, Maybe<bool>* stackChanged)
+{
+ class EnableLiveEditScope {
+ public:
+ explicit EnableLiveEditScope(v8::Isolate* isolate) : m_isolate(isolate)
+ {
+ v8::Debug::SetLiveEditEnabled(m_isolate, true);
+ inLiveEditScope = true;
+ }
+ ~EnableLiveEditScope()
+ {
+ v8::Debug::SetLiveEditEnabled(m_isolate, false);
+ inLiveEditScope = false;
+ }
+ private:
+ v8::Isolate* m_isolate;
+ };
+
+ DCHECK(enabled());
+ v8::HandleScope scope(m_isolate);
+
+ std::unique_ptr<v8::Context::Scope> contextScope;
+ if (!isPaused())
+ contextScope = wrapUnique(new v8::Context::Scope(debuggerContext()));
+
+ v8::Local<v8::Value> argv[] = { toV8String(m_isolate, sourceID), toV8String(m_isolate, newContent), v8Boolean(preview, m_isolate) };
+
+ v8::Local<v8::Value> v8result;
+ {
+ EnableLiveEditScope enableLiveEditScope(m_isolate);
+ v8::TryCatch tryCatch(m_isolate);
+ tryCatch.SetVerbose(false);
+ v8::MaybeLocal<v8::Value> maybeResult = callDebuggerMethod("liveEditScriptSource", 3, argv);
+ if (tryCatch.HasCaught()) {
+ v8::Local<v8::Message> message = tryCatch.Message();
+ if (!message.IsEmpty())
+ *error = toProtocolStringWithTypeCheck(message->Get());
+ else
+ *error = "Unknown error.";
+ return false;
+ }
+ v8result = maybeResult.ToLocalChecked();
+ }
+ DCHECK(!v8result.IsEmpty());
+ v8::Local<v8::Object> resultTuple = v8result->ToObject(m_isolate);
+ int code = static_cast<int>(resultTuple->Get(0)->ToInteger(m_isolate)->Value());
+ switch (code) {
+ case 0:
+ {
+ *stackChanged = resultTuple->Get(1)->BooleanValue();
+ // Call stack may have changed after if the edited function was on the stack.
+ if (!preview && isPaused())
+ newCallFrames->swap(currentCallFrames());
+ return true;
+ }
+ // Compile error.
+ case 1:
+ {
+ *errorData = protocol::Debugger::SetScriptSourceError::create()
+ .setMessage(toProtocolStringWithTypeCheck(resultTuple->Get(2)))
+ .setLineNumber(resultTuple->Get(3)->ToInteger(m_isolate)->Value())
+ .setColumnNumber(resultTuple->Get(4)->ToInteger(m_isolate)->Value()).build();
+ return false;
+ }
+ }
+ *error = "Unknown error.";
+ return false;
+}
+
+JavaScriptCallFrames V8DebuggerImpl::currentCallFrames(int limit)
+{
+ if (!m_isolate->InContext())
+ return JavaScriptCallFrames();
+ v8::Local<v8::Value> currentCallFramesV8;
+ if (m_executionState.IsEmpty()) {
+ v8::Local<v8::Function> currentCallFramesFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.Get(m_isolate)->Get(v8InternalizedString("currentCallFrames")));
+ currentCallFramesV8 = v8::Debug::Call(debuggerContext(), currentCallFramesFunction, v8::Integer::New(m_isolate, limit)).ToLocalChecked();
+ } else {
+ v8::Local<v8::Value> argv[] = { m_executionState, v8::Integer::New(m_isolate, limit) };
+ currentCallFramesV8 = callDebuggerMethod("currentCallFrames", PROTOCOL_ARRAY_LENGTH(argv), argv).ToLocalChecked();
+ }
+ DCHECK(!currentCallFramesV8.IsEmpty());
+ if (!currentCallFramesV8->IsArray())
+ return JavaScriptCallFrames();
+ v8::Local<v8::Array> callFramesArray = currentCallFramesV8.As<v8::Array>();
+ JavaScriptCallFrames callFrames;
+ for (size_t i = 0; i < callFramesArray->Length(); ++i) {
+ v8::Local<v8::Value> callFrameValue;
+ if (!callFramesArray->Get(debuggerContext(), i).ToLocal(&callFrameValue))
+ return JavaScriptCallFrames();
+ if (!callFrameValue->IsObject())
+ return JavaScriptCallFrames();
+ v8::Local<v8::Object> callFrameObject = callFrameValue.As<v8::Object>();
+ callFrames.append(JavaScriptCallFrame::create(debuggerContext(), v8::Local<v8::Object>::Cast(callFrameObject)));
+ }
+ return callFrames;
+}
+
+static V8DebuggerImpl* toV8DebuggerImpl(v8::Local<v8::Value> data)
+{
+ void* p = v8::Local<v8::External>::Cast(data)->Value();
+ return static_cast<V8DebuggerImpl*>(p);
+}
+
+void V8DebuggerImpl::breakProgramCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ DCHECK(2 == info.Length());
+ V8DebuggerImpl* thisPtr = toV8DebuggerImpl(info.Data());
+ v8::Local<v8::Context> pausedContext = thisPtr->m_isolate->GetCurrentContext();
+ v8::Local<v8::Value> exception;
+ v8::Local<v8::Array> hitBreakpoints;
+ thisPtr->handleProgramBreak(pausedContext, v8::Local<v8::Object>::Cast(info[0]), exception, hitBreakpoints);
+}
+
+void V8DebuggerImpl::handleProgramBreak(v8::Local<v8::Context> pausedContext, v8::Local<v8::Object> executionState, v8::Local<v8::Value> exception, v8::Local<v8::Array> hitBreakpointNumbers, bool isPromiseRejection)
+{
+ // Don't allow nested breaks.
+ if (m_runningNestedMessageLoop)
+ return;
+
+ V8DebuggerAgentImpl* agent = findEnabledDebuggerAgent(pausedContext);
+ if (!agent)
+ return;
+
+ protocol::Vector<String16> breakpointIds;
+ if (!hitBreakpointNumbers.IsEmpty()) {
+ breakpointIds.resize(hitBreakpointNumbers->Length());
+ for (size_t i = 0; i < hitBreakpointNumbers->Length(); i++) {
+ v8::Local<v8::Value> hitBreakpointNumber = hitBreakpointNumbers->Get(i);
+ DCHECK(!hitBreakpointNumber.IsEmpty() && hitBreakpointNumber->IsInt32());
+ breakpointIds[i] = String16::number(hitBreakpointNumber->Int32Value());
+ }
+ }
+
+ m_pausedContext = pausedContext;
+ m_executionState = executionState;
+ V8DebuggerAgentImpl::SkipPauseRequest result = agent->didPause(pausedContext, exception, breakpointIds, isPromiseRejection);
+ if (result == V8DebuggerAgentImpl::RequestNoSkip) {
+ m_runningNestedMessageLoop = true;
+ int groupId = getGroupId(pausedContext);
+ DCHECK(groupId);
+ m_client->runMessageLoopOnPause(groupId);
+ // The agent may have been removed in the nested loop.
+ agent = findEnabledDebuggerAgent(pausedContext);
+ if (agent)
+ agent->didContinue();
+ m_runningNestedMessageLoop = false;
+ }
+ m_pausedContext.Clear();
+ m_executionState.Clear();
+
+ if (result == V8DebuggerAgentImpl::RequestStepFrame) {
+ v8::Local<v8::Value> argv[] = { executionState };
+ callDebuggerMethod("stepFrameStatement", 1, argv);
+ } else if (result == V8DebuggerAgentImpl::RequestStepInto) {
+ v8::Local<v8::Value> argv[] = { executionState };
+ callDebuggerMethod(stepIntoV8MethodName, 1, argv);
+ } else if (result == V8DebuggerAgentImpl::RequestStepOut) {
+ v8::Local<v8::Value> argv[] = { executionState };
+ callDebuggerMethod(stepOutV8MethodName, 1, argv);
+ }
+}
+
+void V8DebuggerImpl::v8DebugEventCallback(const v8::Debug::EventDetails& eventDetails)
+{
+ V8DebuggerImpl* thisPtr = toV8DebuggerImpl(eventDetails.GetCallbackData());
+ thisPtr->handleV8DebugEvent(eventDetails);
+}
+
+v8::Local<v8::Value> V8DebuggerImpl::callInternalGetterFunction(v8::Local<v8::Object> object, const char* functionName)
+{
+ v8::MicrotasksScope microtasks(m_isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
+ v8::Local<v8::Value> getterValue = object->Get(v8InternalizedString(functionName));
+ DCHECK(!getterValue.IsEmpty() && getterValue->IsFunction());
+ return v8::Local<v8::Function>::Cast(getterValue)->Call(m_isolate->GetCurrentContext(), object, 0, 0).ToLocalChecked();
+}
+
+void V8DebuggerImpl::handleV8DebugEvent(const v8::Debug::EventDetails& eventDetails)
+{
+ if (!enabled())
+ return;
+ v8::DebugEvent event = eventDetails.GetEvent();
+ if (event != v8::AsyncTaskEvent && event != v8::Break && event != v8::Exception && event != v8::AfterCompile && event != v8::BeforeCompile && event != v8::CompileError)
+ return;
+
+ v8::Local<v8::Context> eventContext = eventDetails.GetEventContext();
+ DCHECK(!eventContext.IsEmpty());
+
+ V8DebuggerAgentImpl* agent = findEnabledDebuggerAgent(eventContext);
+ if (agent) {
+ v8::HandleScope scope(m_isolate);
+ if (event == v8::AfterCompile || event == v8::CompileError) {
+ v8::Context::Scope contextScope(debuggerContext());
+ v8::Local<v8::Value> argv[] = { eventDetails.GetEventData() };
+ v8::Local<v8::Value> value = callDebuggerMethod("getAfterCompileScript", 1, argv).ToLocalChecked();
+ DCHECK(value->IsObject());
+ v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);
+ agent->didParseSource(createParsedScript(object, event == v8::AfterCompile));
+ } else if (event == v8::Exception) {
+ v8::Local<v8::Object> eventData = eventDetails.GetEventData();
+ v8::Local<v8::Value> exception = callInternalGetterFunction(eventData, "exception");
+ v8::Local<v8::Value> promise = callInternalGetterFunction(eventData, "promise");
+ bool isPromiseRejection = !promise.IsEmpty() && promise->IsObject();
+ handleProgramBreak(eventContext, eventDetails.GetExecutionState(), exception, v8::Local<v8::Array>(), isPromiseRejection);
+ } else if (event == v8::Break) {
+ v8::Local<v8::Value> argv[] = { eventDetails.GetEventData() };
+ v8::Local<v8::Value> hitBreakpoints = callDebuggerMethod("getBreakpointNumbers", 1, argv).ToLocalChecked();
+ DCHECK(hitBreakpoints->IsArray());
+ handleProgramBreak(eventContext, eventDetails.GetExecutionState(), v8::Local<v8::Value>(), hitBreakpoints.As<v8::Array>());
+ } else if (event == v8::AsyncTaskEvent) {
+ if (agent->v8AsyncTaskEventsEnabled())
+ handleV8AsyncTaskEvent(agent, eventContext, eventDetails.GetExecutionState(), eventDetails.GetEventData());
+ }
+ }
+}
+
+void V8DebuggerImpl::handleV8AsyncTaskEvent(V8DebuggerAgentImpl* agent, v8::Local<v8::Context> context, v8::Local<v8::Object> executionState, v8::Local<v8::Object> eventData)
+{
+ String16 type = toProtocolStringWithTypeCheck(callInternalGetterFunction(eventData, "type"));
+ String16 name = toProtocolStringWithTypeCheck(callInternalGetterFunction(eventData, "name"));
+ int id = callInternalGetterFunction(eventData, "id")->ToInteger(m_isolate)->Value();
+
+ m_pausedContext = context;
+ m_executionState = executionState;
+ agent->didReceiveV8AsyncTaskEvent(context, type, name, id);
+ m_pausedContext.Clear();
+ m_executionState.Clear();
+}
+
+V8DebuggerParsedScript V8DebuggerImpl::createParsedScript(v8::Local<v8::Object> object, bool success)
+{
+ v8::Local<v8::Value> id = object->Get(v8InternalizedString("id"));
+ DCHECK(!id.IsEmpty() && id->IsInt32());
+
+ V8DebuggerParsedScript parsedScript;
+ parsedScript.scriptId = String16::number(id->Int32Value());
+ parsedScript.script.setURL(toProtocolStringWithTypeCheck(object->Get(v8InternalizedString("name"))))
+ .setSourceURL(toProtocolStringWithTypeCheck(object->Get(v8InternalizedString("sourceURL"))))
+ .setSourceMappingURL(toProtocolStringWithTypeCheck(object->Get(v8InternalizedString("sourceMappingURL"))))
+ .setSource(toProtocolStringWithTypeCheck(object->Get(v8InternalizedString("source"))))
+ .setStartLine(object->Get(v8InternalizedString("startLine"))->ToInteger(m_isolate)->Value())
+ .setStartColumn(object->Get(v8InternalizedString("startColumn"))->ToInteger(m_isolate)->Value())
+ .setEndLine(object->Get(v8InternalizedString("endLine"))->ToInteger(m_isolate)->Value())
+ .setEndColumn(object->Get(v8InternalizedString("endColumn"))->ToInteger(m_isolate)->Value())
+ .setIsContentScript(object->Get(v8InternalizedString("isContentScript"))->ToBoolean(m_isolate)->Value())
+ .setIsInternalScript(object->Get(v8InternalizedString("isInternalScript"))->ToBoolean(m_isolate)->Value())
+ .setExecutionContextId(object->Get(v8InternalizedString("executionContextId"))->ToInteger(m_isolate)->Value())
+ .setIsLiveEdit(inLiveEditScope);
+ parsedScript.success = success;
+ return parsedScript;
+}
+
+void V8DebuggerImpl::compileDebuggerScript()
+{
+ if (!m_debuggerScript.IsEmpty()) {
+ NOTREACHED();
+ return;
+ }
+
+ v8::HandleScope scope(m_isolate);
+ v8::Context::Scope contextScope(debuggerContext());
+
+ v8::Local<v8::String> scriptValue = v8::String::NewFromUtf8(m_isolate, DebuggerScript_js, v8::NewStringType::kInternalized, sizeof(DebuggerScript_js)).ToLocalChecked();
+ v8::Local<v8::Value> value;
+ if (!compileAndRunInternalScript(debuggerContext(), scriptValue).ToLocal(&value))
+ return;
+ DCHECK(value->IsObject());
+ m_debuggerScript.Reset(m_isolate, value.As<v8::Object>());
+}
+
+v8::Local<v8::Context> V8DebuggerImpl::debuggerContext() const
+{
+ DCHECK(!m_debuggerContext.IsEmpty());
+ return m_debuggerContext.Get(m_isolate);
+}
+
+v8::Local<v8::String> V8DebuggerImpl::v8InternalizedString(const char* str) const
+{
+ return v8::String::NewFromUtf8(m_isolate, str, v8::NewStringType::kInternalized).ToLocalChecked();
+}
+
+v8::MaybeLocal<v8::Value> V8DebuggerImpl::functionScopes(v8::Local<v8::Function> function)
+{
+ if (!enabled()) {
+ NOTREACHED();
+ return v8::Local<v8::Value>::New(m_isolate, v8::Undefined(m_isolate));
+ }
+ v8::Local<v8::Value> argv[] = { function };
+ return callDebuggerMethod("getFunctionScopes", 1, argv);
+}
+
+v8::Local<v8::Value> V8DebuggerImpl::generatorObjectDetails(v8::Local<v8::Object>& object)
+{
+ if (!enabled()) {
+ NOTREACHED();
+ return v8::Local<v8::Value>::New(m_isolate, v8::Undefined(m_isolate));
+ }
+ v8::Local<v8::Value> argv[] = { object };
+ return callDebuggerMethod("getGeneratorObjectDetails", 1, argv).ToLocalChecked();
+}
+
+v8::Local<v8::Value> V8DebuggerImpl::collectionEntries(v8::Local<v8::Object>& object)
+{
+ if (!enabled()) {
+ NOTREACHED();
+ return v8::Local<v8::Value>::New(m_isolate, v8::Undefined(m_isolate));
+ }
+ v8::Local<v8::Value> argv[] = { object };
+ return callDebuggerMethod("getCollectionEntries", 1, argv).ToLocalChecked();
+}
+
+bool V8DebuggerImpl::isPaused()
+{
+ return !m_pausedContext.IsEmpty();
+}
+
+v8::MaybeLocal<v8::Value> V8DebuggerImpl::runCompiledScript(v8::Local<v8::Context> context, v8::Local<v8::Script> script)
+{
+ // TODO(dgozman): get rid of this check.
+ if (!m_client->isExecutionAllowed())
+ return v8::MaybeLocal<v8::Value>();
+
+ v8::MicrotasksScope microtasksScope(m_isolate, v8::MicrotasksScope::kRunMicrotasks);
+ int groupId = getGroupId(context);
+ if (V8DebuggerAgentImpl* agent = findEnabledDebuggerAgent(groupId))
+ agent->willExecuteScript(script->GetUnboundScript()->GetId());
+ v8::MaybeLocal<v8::Value> result = script->Run(context);
+ // Get agent from the map again, since it could have detached during script execution.
+ if (V8DebuggerAgentImpl* agent = findEnabledDebuggerAgent(groupId))
+ agent->didExecuteScript();
+ return result;
+}
+
+v8::MaybeLocal<v8::Value> V8DebuggerImpl::callFunction(v8::Local<v8::Function> function, v8::Local<v8::Context> context, v8::Local<v8::Value> receiver, int argc, v8::Local<v8::Value> info[])
+{
+ // TODO(dgozman): get rid of this check.
+ if (!m_client->isExecutionAllowed())
+ return v8::MaybeLocal<v8::Value>();
+
+ v8::MicrotasksScope microtasksScope(m_isolate, v8::MicrotasksScope::kRunMicrotasks);
+ int groupId = getGroupId(context);
+ if (V8DebuggerAgentImpl* agent = findEnabledDebuggerAgent(groupId))
+ agent->willExecuteScript(function->ScriptId());
+ v8::MaybeLocal<v8::Value> result = function->Call(context, receiver, argc, info);
+ // Get agent from the map again, since it could have detached during script execution.
+ if (V8DebuggerAgentImpl* agent = findEnabledDebuggerAgent(groupId))
+ agent->didExecuteScript();
+ return result;
+}
+
+v8::MaybeLocal<v8::Value> V8DebuggerImpl::compileAndRunInternalScript(v8::Local<v8::Context> context, v8::Local<v8::String> source)
+{
+ v8::Local<v8::Script> script = compileInternalScript(context, source, String());
+ if (script.IsEmpty())
+ return v8::MaybeLocal<v8::Value>();
+ v8::MicrotasksScope microtasksScope(m_isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
+ return script->Run(context);
+}
+
+v8::Local<v8::Script> V8DebuggerImpl::compileInternalScript(v8::Local<v8::Context> context, v8::Local<v8::String> code, const String16& fileName)
+{
+ // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at
+ // 1, whereas v8 starts at 0.
+ v8::ScriptOrigin origin(
+ toV8String(m_isolate, fileName),
+ v8::Integer::New(m_isolate, 0),
+ v8::Integer::New(m_isolate, 0),
+ v8::False(m_isolate), // sharable
+ v8::Local<v8::Integer>(),
+ v8::True(m_isolate), // internal
+ toV8String(m_isolate, String16()), // sourceMap
+ v8::True(m_isolate)); // opaqueresource
+ v8::ScriptCompiler::Source source(code, origin);
+ v8::Local<v8::Script> script;
+ if (!v8::ScriptCompiler::Compile(context, &source, v8::ScriptCompiler::kNoCompileOptions).ToLocal(&script))
+ return v8::Local<v8::Script>();
+ return script;
+}
+
+std::unique_ptr<V8StackTrace> V8DebuggerImpl::createStackTrace(v8::Local<v8::StackTrace> stackTrace, size_t maxStackSize)
+{
+ V8DebuggerAgentImpl* agent = findEnabledDebuggerAgent(m_isolate->GetCurrentContext());
+ return V8StackTraceImpl::create(agent, stackTrace, maxStackSize);
+}
+
+std::unique_ptr<V8InspectorSession> V8DebuggerImpl::connect(int contextGroupId)
+{
+ DCHECK(!m_sessions.contains(contextGroupId));
+ std::unique_ptr<V8InspectorSessionImpl> session = V8InspectorSessionImpl::create(this, contextGroupId);
+ m_sessions.set(contextGroupId, session.get());
+ return std::move(session);
+}
+
+void V8DebuggerImpl::disconnect(V8InspectorSessionImpl* session)
+{
+ DCHECK(m_sessions.contains(session->contextGroupId()));
+ m_sessions.remove(session->contextGroupId());
+}
+
+void V8DebuggerImpl::contextCreated(const V8ContextInfo& info)
+{
+ DCHECK(info.context->GetIsolate() == m_isolate);
+ // TODO(dgozman): make s_lastContextId non-static.
+ int contextId = atomicIncrement(&s_lastContextId);
+ String16 debugData = String16::number(info.contextGroupId) + "," + String16::number(contextId) + "," + (info.isDefault ? "default" : "nondefault");
+ v8::HandleScope scope(m_isolate);
+ v8::Context::Scope contextScope(info.context);
+ info.context->SetEmbedderData(static_cast<int>(v8::Context::kDebugIdIndex), toV8String(m_isolate, debugData));
+
+ if (!m_contexts.contains(info.contextGroupId))
+ m_contexts.set(info.contextGroupId, wrapUnique(new ContextByIdMap()));
+ DCHECK(!m_contexts.get(info.contextGroupId)->contains(contextId));
+
+ std::unique_ptr<InspectedContext> contextOwner(new InspectedContext(this, info, contextId));
+ InspectedContext* inspectedContext = contextOwner.get();
+ m_contexts.get(info.contextGroupId)->set(contextId, std::move(contextOwner));
+
+ if (V8InspectorSessionImpl* session = m_sessions.get(info.contextGroupId))
+ session->runtimeAgentImpl()->reportExecutionContextCreated(inspectedContext);
+}
+
+void V8DebuggerImpl::contextDestroyed(v8::Local<v8::Context> context)
+{
+ int contextId = V8Debugger::contextId(context);
+ int contextGroupId = getGroupId(context);
+ if (!m_contexts.contains(contextGroupId) || !m_contexts.get(contextGroupId)->contains(contextId))
+ return;
+
+ InspectedContext* inspectedContext = m_contexts.get(contextGroupId)->get(contextId);
+ if (V8InspectorSessionImpl* session = m_sessions.get(contextGroupId))
+ session->runtimeAgentImpl()->reportExecutionContextDestroyed(inspectedContext);
+
+ m_contexts.get(contextGroupId)->remove(contextId);
+ if (m_contexts.get(contextGroupId)->isEmpty())
+ m_contexts.remove(contextGroupId);
+}
+
+void V8DebuggerImpl::resetContextGroup(int contextGroupId)
+{
+ if (V8InspectorSessionImpl* session = m_sessions.get(contextGroupId))
+ session->reset();
+ m_contexts.remove(contextGroupId);
+}
+
+void V8DebuggerImpl::willExecuteScript(v8::Local<v8::Context> context, int scriptId)
+{
+ if (V8DebuggerAgentImpl* agent = findEnabledDebuggerAgent(context))
+ agent->willExecuteScript(scriptId);
+}
+
+void V8DebuggerImpl::didExecuteScript(v8::Local<v8::Context> context)
+{
+ if (V8DebuggerAgentImpl* agent = findEnabledDebuggerAgent(context))
+ agent->didExecuteScript();
+}
+
+void V8DebuggerImpl::idleStarted()
+{
+ m_isolate->GetCpuProfiler()->SetIdle(true);
+}
+
+void V8DebuggerImpl::idleFinished()
+{
+ m_isolate->GetCpuProfiler()->SetIdle(false);
+}
+
+std::unique_ptr<V8StackTrace> V8DebuggerImpl::captureStackTrace(size_t maxStackSize)
+{
+ V8DebuggerAgentImpl* agent = findEnabledDebuggerAgent(m_isolate->GetCurrentContext());
+ return V8StackTraceImpl::capture(agent, maxStackSize);
+}
+
+v8::Local<v8::Context> V8DebuggerImpl::regexContext()
+{
+ if (m_regexContext.IsEmpty())
+ m_regexContext.Reset(m_isolate, v8::Context::New(m_isolate));
+ return m_regexContext.Get(m_isolate);
+}
+
+void V8DebuggerImpl::discardInspectedContext(int contextGroupId, int contextId)
+{
+ if (!m_contexts.contains(contextGroupId) || !m_contexts.get(contextGroupId)->contains(contextId))
+ return;
+ m_contexts.get(contextGroupId)->remove(contextId);
+ if (m_contexts.get(contextGroupId)->isEmpty())
+ m_contexts.remove(contextGroupId);
+}
+
+const V8DebuggerImpl::ContextByIdMap* V8DebuggerImpl::contextGroup(int contextGroupId)
+{
+ if (!m_contexts.contains(contextGroupId))
+ return nullptr;
+ return m_contexts.get(contextGroupId);
+}
+
+V8InspectorSessionImpl* V8DebuggerImpl::sessionForContextGroup(int contextGroupId)
+{
+ return contextGroupId ? m_sessions.get(contextGroupId) : nullptr;
+}
+
+} // namespace blink
diff --git a/deps/v8_inspector/platform/v8_inspector/V8DebuggerImpl.h b/deps/v8_inspector/platform/v8_inspector/V8DebuggerImpl.h
new file mode 100644
index 0000000000..48f335004a
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8DebuggerImpl.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef V8DebuggerImpl_h
+#define V8DebuggerImpl_h
+
+#include "platform/inspector_protocol/TypeBuilder.h"
+#include "platform/v8_inspector/JavaScriptCallFrame.h"
+#include "platform/v8_inspector/V8DebuggerScript.h"
+#include "platform/v8_inspector/public/V8Debugger.h"
+#include "wtf/PtrUtil.h"
+
+#include <v8-debug.h>
+#include <v8.h>
+
+namespace blink {
+
+using protocol::Maybe;
+
+struct ScriptBreakpoint;
+class InspectedContext;
+class V8DebuggerAgentImpl;
+class V8InspectorSessionImpl;
+class V8RuntimeAgentImpl;
+
+class V8DebuggerImpl : public V8Debugger {
+ PROTOCOL_DISALLOW_COPY(V8DebuggerImpl);
+public:
+ V8DebuggerImpl(v8::Isolate*, V8DebuggerClient*);
+ ~V8DebuggerImpl() override;
+
+ bool enabled() const;
+
+ String16 setBreakpoint(const String16& sourceID, const ScriptBreakpoint&, int* actualLineNumber, int* actualColumnNumber, bool interstatementLocation);
+ void removeBreakpoint(const String16& breakpointId);
+ void setBreakpointsActivated(bool);
+ bool breakpointsActivated() const { return m_breakpointsActivated; }
+
+ enum PauseOnExceptionsState {
+ DontPauseOnExceptions,
+ PauseOnAllExceptions,
+ PauseOnUncaughtExceptions
+ };
+ PauseOnExceptionsState getPauseOnExceptionsState();
+ void setPauseOnExceptionsState(PauseOnExceptionsState);
+ void setPauseOnNextStatement(bool);
+ bool canBreakProgram();
+ void breakProgram();
+ void continueProgram();
+ void stepIntoStatement();
+ void stepOverStatement();
+ void stepOutOfFunction();
+ void clearStepping();
+
+ bool setScriptSource(const String16& sourceID, const String16& newContent, bool preview, ErrorString*, Maybe<protocol::Debugger::SetScriptSourceError>*, JavaScriptCallFrames* newCallFrames, Maybe<bool>* stackChanged);
+ JavaScriptCallFrames currentCallFrames(int limit = 0);
+
+ // Each script inherits debug data from v8::Context where it has been compiled.
+ // Only scripts whose debug data matches |contextGroupId| will be reported.
+ // Passing 0 will result in reporting all scripts.
+ void getCompiledScripts(int contextGroupId, protocol::Vector<V8DebuggerParsedScript>&);
+ void debuggerAgentEnabled();
+ void debuggerAgentDisabled();
+
+ bool isPaused() override;
+ v8::Local<v8::Context> pausedContext() { return m_pausedContext; }
+
+ v8::MaybeLocal<v8::Value> functionScopes(v8::Local<v8::Function>);
+ v8::Local<v8::Value> generatorObjectDetails(v8::Local<v8::Object>&);
+ v8::Local<v8::Value> collectionEntries(v8::Local<v8::Object>&);
+
+ v8::Isolate* isolate() const { return m_isolate; }
+ V8DebuggerClient* client() { return m_client; }
+
+ v8::MaybeLocal<v8::Value> runCompiledScript(v8::Local<v8::Context>, v8::Local<v8::Script>);
+ v8::MaybeLocal<v8::Value> callFunction(v8::Local<v8::Function>, v8::Local<v8::Context>, v8::Local<v8::Value> receiver, int argc, v8::Local<v8::Value> info[]);
+ v8::MaybeLocal<v8::Value> compileAndRunInternalScript(v8::Local<v8::Context>, v8::Local<v8::String>);
+ v8::Local<v8::Script> compileInternalScript(v8::Local<v8::Context>, v8::Local<v8::String>, const String16& fileName);
+ v8::Local<v8::Context> regexContext();
+
+ // V8Debugger implementation
+ std::unique_ptr<V8InspectorSession> connect(int contextGroupId) override;
+ void contextCreated(const V8ContextInfo&) override;
+ void contextDestroyed(v8::Local<v8::Context>) override;
+ void resetContextGroup(int contextGroupId) override;
+ void willExecuteScript(v8::Local<v8::Context>, int scriptId) override;
+ void didExecuteScript(v8::Local<v8::Context>) override;
+ void idleStarted() override;
+ void idleFinished() override;
+ std::unique_ptr<V8StackTrace> createStackTrace(v8::Local<v8::StackTrace>, size_t maxStackSize) override;
+ std::unique_ptr<V8StackTrace> captureStackTrace(size_t maxStackSize) override;
+
+ using ContextByIdMap = protocol::HashMap<int, std::unique_ptr<InspectedContext>>;
+ void discardInspectedContext(int contextGroupId, int contextId);
+ const ContextByIdMap* contextGroup(int contextGroupId);
+ void disconnect(V8InspectorSessionImpl*);
+ V8InspectorSessionImpl* sessionForContextGroup(int contextGroupId);
+
+private:
+ void enable();
+ void disable();
+ V8DebuggerAgentImpl* findEnabledDebuggerAgent(int contextGroupId);
+ V8DebuggerAgentImpl* findEnabledDebuggerAgent(v8::Local<v8::Context>);
+
+ void compileDebuggerScript();
+ v8::MaybeLocal<v8::Value> callDebuggerMethod(const char* functionName, int argc, v8::Local<v8::Value> argv[]);
+ v8::Local<v8::Context> debuggerContext() const;
+ void clearBreakpoints();
+
+ V8DebuggerParsedScript createParsedScript(v8::Local<v8::Object> sourceObject, bool success);
+
+ static void breakProgramCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ void handleProgramBreak(v8::Local<v8::Context> pausedContext, v8::Local<v8::Object> executionState, v8::Local<v8::Value> exception, v8::Local<v8::Array> hitBreakpoints, bool isPromiseRejection = false);
+ static void v8DebugEventCallback(const v8::Debug::EventDetails&);
+ v8::Local<v8::Value> callInternalGetterFunction(v8::Local<v8::Object>, const char* functionName);
+ void handleV8DebugEvent(const v8::Debug::EventDetails&);
+
+ v8::Local<v8::String> v8InternalizedString(const char*) const;
+
+ void handleV8AsyncTaskEvent(V8DebuggerAgentImpl*, v8::Local<v8::Context>, v8::Local<v8::Object> executionState, v8::Local<v8::Object> eventData);
+
+ v8::Isolate* m_isolate;
+ V8DebuggerClient* m_client;
+ using ContextsByGroupMap = protocol::HashMap<int, std::unique_ptr<ContextByIdMap>>;
+ ContextsByGroupMap m_contexts;
+ using SessionMap = protocol::HashMap<int, V8InspectorSessionImpl*>;
+ SessionMap m_sessions;
+ int m_enabledAgentsCount;
+ bool m_breakpointsActivated;
+ v8::Global<v8::Object> m_debuggerScript;
+ v8::Global<v8::Context> m_debuggerContext;
+ v8::Local<v8::Object> m_executionState;
+ v8::Local<v8::Context> m_pausedContext;
+ bool m_runningNestedMessageLoop;
+ v8::Global<v8::Context> m_regexContext;
+};
+
+} // namespace blink
+
+
+#endif // V8DebuggerImpl_h
diff --git a/deps/v8_inspector/platform/v8_inspector/V8DebuggerScript.cpp b/deps/v8_inspector/platform/v8_inspector/V8DebuggerScript.cpp
new file mode 100644
index 0000000000..14dba693e9
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8DebuggerScript.cpp
@@ -0,0 +1,104 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/v8_inspector/V8DebuggerScript.h"
+
+namespace blink {
+
+V8DebuggerScript::V8DebuggerScript()
+ : m_startLine(0)
+ , m_startColumn(0)
+ , m_endLine(0)
+ , m_endColumn(0)
+ , m_executionContextId(0)
+ , m_isContentScript(false)
+ , m_isInternalScript(false)
+ , m_isLiveEdit(false)
+{
+}
+
+String16 V8DebuggerScript::sourceURL() const
+{
+ return m_sourceURL.isEmpty() ? m_url : m_sourceURL;
+}
+
+V8DebuggerScript& V8DebuggerScript::setURL(const String16& url)
+{
+ m_url = url;
+ return *this;
+}
+
+V8DebuggerScript& V8DebuggerScript::setSourceURL(const String16& sourceURL)
+{
+ m_sourceURL = sourceURL;
+ return *this;
+}
+
+V8DebuggerScript& V8DebuggerScript::setSourceMappingURL(const String16& sourceMappingURL)
+{
+ m_sourceMappingURL = sourceMappingURL;
+ return *this;
+}
+
+V8DebuggerScript& V8DebuggerScript::setSource(const String16& source)
+{
+ m_source = source;
+ return *this;
+}
+
+V8DebuggerScript& V8DebuggerScript::setHash(const String16& hash)
+{
+ m_hash = hash;
+ return *this;
+}
+
+V8DebuggerScript& V8DebuggerScript::setStartLine(int startLine)
+{
+ m_startLine = startLine;
+ return *this;
+}
+
+V8DebuggerScript& V8DebuggerScript::setStartColumn(int startColumn)
+{
+ m_startColumn = startColumn;
+ return *this;
+}
+
+V8DebuggerScript& V8DebuggerScript::setEndLine(int endLine)
+{
+ m_endLine = endLine;
+ return *this;
+}
+
+V8DebuggerScript& V8DebuggerScript::setEndColumn(int endColumn)
+{
+ m_endColumn = endColumn;
+ return *this;
+}
+
+V8DebuggerScript& V8DebuggerScript::setExecutionContextId(int executionContextId)
+{
+ m_executionContextId = executionContextId;
+ return *this;
+}
+
+V8DebuggerScript& V8DebuggerScript::setIsContentScript(bool isContentScript)
+{
+ m_isContentScript = isContentScript;
+ return *this;
+}
+
+V8DebuggerScript& V8DebuggerScript::setIsInternalScript(bool isInternalScript)
+{
+ m_isInternalScript = isInternalScript;
+ return *this;
+}
+
+V8DebuggerScript& V8DebuggerScript::setIsLiveEdit(bool isLiveEdit)
+{
+ m_isLiveEdit = isLiveEdit;
+ return *this;
+}
+
+} // namespace blink
diff --git a/deps/v8_inspector/platform/v8_inspector/V8DebuggerScript.h b/deps/v8_inspector/platform/v8_inspector/V8DebuggerScript.h
new file mode 100644
index 0000000000..55080be0da
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8DebuggerScript.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef V8DebuggerScript_h
+#define V8DebuggerScript_h
+
+#include "platform/inspector_protocol/Allocator.h"
+#include "platform/inspector_protocol/String16.h"
+#include <v8.h>
+
+namespace blink {
+
+class V8DebuggerScript {
+ PROTOCOL_DISALLOW_NEW();
+public:
+ V8DebuggerScript();
+
+ String16 url() const { return m_url; }
+ bool hasSourceURL() const { return !m_sourceURL.isEmpty(); }
+ String16 sourceURL() const;
+ String16 sourceMappingURL() const { return m_sourceMappingURL; }
+ String16 source() const { return m_source; }
+ String16 hash() const { return m_hash; }
+ int startLine() const { return m_startLine; }
+ int startColumn() const { return m_startColumn; }
+ int endLine() const { return m_endLine; }
+ int endColumn() const { return m_endColumn; }
+ int executionContextId() const { return m_executionContextId; }
+ bool isContentScript() const { return m_isContentScript; }
+ bool isInternalScript() const { return m_isInternalScript; }
+ bool isLiveEdit() const { return m_isLiveEdit; }
+
+ V8DebuggerScript& setURL(const String16&);
+ V8DebuggerScript& setSourceURL(const String16&);
+ V8DebuggerScript& setSourceMappingURL(const String16&);
+ V8DebuggerScript& setSource(const String16&);
+ V8DebuggerScript& setHash(const String16&);
+ V8DebuggerScript& setStartLine(int);
+ V8DebuggerScript& setStartColumn(int);
+ V8DebuggerScript& setEndLine(int);
+ V8DebuggerScript& setEndColumn(int);
+ V8DebuggerScript& setExecutionContextId(int);
+ V8DebuggerScript& setIsContentScript(bool);
+ V8DebuggerScript& setIsInternalScript(bool);
+ V8DebuggerScript& setIsLiveEdit(bool);
+
+private:
+ String16 m_url;
+ String16 m_sourceURL;
+ String16 m_sourceMappingURL;
+ String16 m_source;
+ String16 m_hash;
+ int m_startLine;
+ int m_startColumn;
+ int m_endLine;
+ int m_endColumn;
+ int m_executionContextId;
+ bool m_isContentScript;
+ bool m_isInternalScript;
+ bool m_isLiveEdit;
+};
+
+struct V8DebuggerParsedScript {
+ String16 scriptId;
+ V8DebuggerScript script;
+ bool success;
+};
+
+} // namespace blink
+
+
+#endif // V8DebuggerScript_h
diff --git a/deps/v8_inspector/platform/v8_inspector/V8FunctionCall.cpp b/deps/v8_inspector/platform/v8_inspector/V8FunctionCall.cpp
new file mode 100644
index 0000000000..872758129d
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8FunctionCall.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "platform/v8_inspector/V8FunctionCall.h"
+
+#include "platform/v8_inspector/V8Compat.h"
+#include "platform/v8_inspector/V8DebuggerImpl.h"
+#include "platform/v8_inspector/V8StringUtil.h"
+#include "platform/v8_inspector/public/V8DebuggerClient.h"
+#include "wtf/PtrUtil.h"
+
+#include <v8.h>
+
+namespace blink {
+
+V8FunctionCall::V8FunctionCall(V8DebuggerImpl* debugger, v8::Local<v8::Context> context, v8::Local<v8::Value> value, const String16& name)
+ : m_debugger(debugger)
+ , m_context(context)
+ , m_name(toV8String(context->GetIsolate(), name))
+ , m_value(value)
+{
+}
+
+void V8FunctionCall::appendArgument(v8::Local<v8::Value> value)
+{
+ m_arguments.append(value);
+}
+
+void V8FunctionCall::appendArgument(const String16& argument)
+{
+ m_arguments.append(toV8String(m_context->GetIsolate(), argument));
+}
+
+void V8FunctionCall::appendArgument(int argument)
+{
+ m_arguments.append(v8::Number::New(m_context->GetIsolate(), argument));
+}
+
+void V8FunctionCall::appendArgument(bool argument)
+{
+ m_arguments.append(argument ? v8::True(m_context->GetIsolate()) : v8::False(m_context->GetIsolate()));
+}
+
+void V8FunctionCall::appendUndefinedArgument()
+{
+ m_arguments.append(v8::Undefined(m_context->GetIsolate()));
+}
+
+v8::Local<v8::Value> V8FunctionCall::call(bool& hadException, bool reportExceptions)
+{
+ v8::TryCatch tryCatch(m_context->GetIsolate());
+ tryCatch.SetVerbose(reportExceptions);
+
+ v8::Local<v8::Value> result = callWithoutExceptionHandling();
+ hadException = tryCatch.HasCaught();
+ return result;
+}
+
+v8::Local<v8::Value> V8FunctionCall::callWithoutExceptionHandling()
+{
+ // TODO(dgozman): get rid of this check.
+ if (!m_debugger->client()->isExecutionAllowed())
+ return v8::Local<v8::Value>();
+
+ v8::Local<v8::Object> thisObject = v8::Local<v8::Object>::Cast(m_value);
+ v8::Local<v8::Value> value;
+ if (!thisObject->Get(m_context, m_name).ToLocal(&value))
+ return v8::Local<v8::Value>();
+
+ DCHECK(value->IsFunction());
+
+ v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(value);
+ std::unique_ptr<v8::Local<v8::Value>[]> info(new v8::Local<v8::Value>[m_arguments.size()]);
+ for (size_t i = 0; i < m_arguments.size(); ++i) {
+ info[i] = m_arguments[i];
+ DCHECK(!info[i].IsEmpty());
+ }
+
+ v8::MicrotasksScope microtasksScope(m_context->GetIsolate(), v8::MicrotasksScope::kDoNotRunMicrotasks);
+ v8::Local<v8::Value> result;
+ if (!function->Call(m_context, thisObject, m_arguments.size(), info.get()).ToLocal(&result))
+ return v8::Local<v8::Value>();
+ return result;
+}
+
+v8::Local<v8::Function> V8FunctionCall::function()
+{
+ v8::TryCatch tryCatch(m_context->GetIsolate());
+ v8::Local<v8::Object> thisObject = v8::Local<v8::Object>::Cast(m_value);
+ v8::Local<v8::Value> value;
+ if (!thisObject->Get(m_context, m_name).ToLocal(&value))
+ return v8::Local<v8::Function>();
+
+ DCHECK(value->IsFunction());
+ return v8::Local<v8::Function>::Cast(value);
+}
+
+} // namespace blink
diff --git a/deps/v8_inspector/platform/v8_inspector/V8FunctionCall.h b/deps/v8_inspector/platform/v8_inspector/V8FunctionCall.h
new file mode 100644
index 0000000000..1c94d240aa
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8FunctionCall.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef V8FunctionCall_h
+#define V8FunctionCall_h
+
+#include "platform/inspector_protocol/Collections.h"
+#include "platform/inspector_protocol/String16.h"
+
+#include <v8.h>
+
+namespace blink {
+
+class V8DebuggerImpl;
+
+class V8FunctionCall {
+public:
+ V8FunctionCall(V8DebuggerImpl*, v8::Local<v8::Context>, v8::Local<v8::Value>, const String16& name);
+
+ void appendArgument(v8::Local<v8::Value>);
+ void appendArgument(const String16&);
+ void appendArgument(int);
+ void appendArgument(bool);
+ void appendUndefinedArgument();
+
+ v8::Local<v8::Value> call(bool& hadException, bool reportExceptions = true);
+ v8::Local<v8::Function> function();
+ v8::Local<v8::Value> callWithoutExceptionHandling();
+ v8::Local<v8::Context> context() { return m_context; }
+
+protected:
+ V8DebuggerImpl* m_debugger;
+ v8::Local<v8::Context> m_context;
+ protocol::Vector<v8::Local<v8::Value>> m_arguments;
+ v8::Local<v8::String> m_name;
+ v8::Local<v8::Value> m_value;
+};
+
+} // namespace blink
+
+#endif // V8FunctionCall
diff --git a/deps/v8_inspector/platform/v8_inspector/V8HeapProfilerAgentImpl.cpp b/deps/v8_inspector/platform/v8_inspector/V8HeapProfilerAgentImpl.cpp
new file mode 100644
index 0000000000..b6f8179cc0
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8HeapProfilerAgentImpl.cpp
@@ -0,0 +1,409 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/v8_inspector/V8HeapProfilerAgentImpl.h"
+
+#include "platform/v8_inspector/InjectedScript.h"
+#include "platform/v8_inspector/V8DebuggerImpl.h"
+#include "platform/v8_inspector/V8InspectorSessionImpl.h"
+#include "platform/v8_inspector/V8StringUtil.h"
+#include "platform/v8_inspector/public/V8DebuggerClient.h"
+#include <v8-profiler.h>
+#include <v8-version.h>
+
+namespace blink {
+
+namespace {
+
+namespace HeapProfilerAgentState {
+static const char heapProfilerEnabled[] = "heapProfilerEnabled";
+static const char heapObjectsTrackingEnabled[] = "heapObjectsTrackingEnabled";
+static const char allocationTrackingEnabled[] = "allocationTrackingEnabled";
+#if V8_MAJOR_VERSION >= 5
+static const char samplingHeapProfilerEnabled[] = "samplingHeapProfilerEnabled";
+static const char samplingHeapProfilerInterval[] = "samplingHeapProfilerInterval";
+#endif
+}
+
+class HeapSnapshotProgress final : public v8::ActivityControl {
+public:
+ HeapSnapshotProgress(protocol::Frontend::HeapProfiler* frontend)
+ : m_frontend(frontend) { }
+ ControlOption ReportProgressValue(int done, int total) override
+ {
+ m_frontend->reportHeapSnapshotProgress(done, total, protocol::Maybe<bool>());
+ if (done >= total) {
+ m_frontend->reportHeapSnapshotProgress(total, total, true);
+ }
+ m_frontend->flush();
+ return kContinue;
+ }
+private:
+ protocol::Frontend::HeapProfiler* m_frontend;
+};
+
+class GlobalObjectNameResolver final : public v8::HeapProfiler::ObjectNameResolver {
+public:
+ explicit GlobalObjectNameResolver(V8InspectorSessionImpl* session) : m_offset(0), m_session(session)
+ {
+ m_strings.resize(10000);
+ }
+
+ const char* GetName(v8::Local<v8::Object> object) override
+ {
+ int contextId = V8Debugger::contextId(object->CreationContext());
+ if (!contextId)
+ return "";
+ ErrorString errorString;
+ InjectedScript* injectedScript = m_session->findInjectedScript(&errorString, contextId);
+ if (!injectedScript)
+ return "";
+ String16 name = injectedScript->context()->origin();
+ size_t length = name.length();
+ if (m_offset + length + 1 >= m_strings.size())
+ return "";
+ for (size_t i = 0; i < length; ++i) {
+ UChar ch = name[i];
+ m_strings[m_offset + i] = ch > 0xff ? '?' : static_cast<char>(ch);
+ }
+ m_strings[m_offset + length] = '\0';
+ char* result = &*m_strings.begin() + m_offset;
+ m_offset += length + 1;
+ return result;
+ }
+
+private:
+ size_t m_offset;
+ protocol::Vector<char> m_strings;
+ V8InspectorSessionImpl* m_session;
+};
+
+class HeapSnapshotOutputStream final : public v8::OutputStream {
+public:
+ HeapSnapshotOutputStream(protocol::Frontend::HeapProfiler* frontend)
+ : m_frontend(frontend) { }
+ void EndOfStream() override { }
+ int GetChunkSize() override { return 102400; }
+ WriteResult WriteAsciiChunk(char* data, int size) override
+ {
+ m_frontend->addHeapSnapshotChunk(String16(data, size));
+ m_frontend->flush();
+ return kContinue;
+ }
+private:
+ protocol::Frontend::HeapProfiler* m_frontend;
+};
+
+v8::Local<v8::Object> objectByHeapObjectId(v8::Isolate* isolate, int id)
+{
+ v8::HeapProfiler* profiler = isolate->GetHeapProfiler();
+ v8::Local<v8::Value> value = profiler->FindObjectById(id);
+ if (value.IsEmpty() || !value->IsObject())
+ return v8::Local<v8::Object>();
+ return value.As<v8::Object>();
+}
+
+class InspectableHeapObject final : public V8InspectorSession::Inspectable {
+public:
+ explicit InspectableHeapObject(int heapObjectId) : m_heapObjectId(heapObjectId) { }
+ v8::Local<v8::Value> get(v8::Local<v8::Context> context) override
+ {
+ return objectByHeapObjectId(context->GetIsolate(), m_heapObjectId);
+ }
+private:
+ int m_heapObjectId;
+};
+
+class HeapStatsStream final : public v8::OutputStream {
+public:
+ HeapStatsStream(protocol::Frontend::HeapProfiler* frontend)
+ : m_frontend(frontend)
+ {
+ }
+
+ void EndOfStream() override { }
+
+ WriteResult WriteAsciiChunk(char* data, int size) override
+ {
+ DCHECK(false);
+ return kAbort;
+ }
+
+ WriteResult WriteHeapStatsChunk(v8::HeapStatsUpdate* updateData, int count) override
+ {
+ DCHECK(count > 0);
+ std::unique_ptr<protocol::Array<int>> statsDiff = protocol::Array<int>::create();
+ for (int i = 0; i < count; ++i) {
+ statsDiff->addItem(updateData[i].index);
+ statsDiff->addItem(updateData[i].count);
+ statsDiff->addItem(updateData[i].size);
+ }
+ m_frontend->heapStatsUpdate(std::move(statsDiff));
+ return kContinue;
+ }
+
+private:
+ protocol::Frontend::HeapProfiler* m_frontend;
+};
+
+} // namespace
+
+V8HeapProfilerAgentImpl::V8HeapProfilerAgentImpl(V8InspectorSessionImpl* session)
+ : m_session(session)
+ , m_isolate(session->debugger()->isolate())
+ , m_hasTimer(false)
+{
+}
+
+V8HeapProfilerAgentImpl::~V8HeapProfilerAgentImpl()
+{
+}
+
+void V8HeapProfilerAgentImpl::clearFrontend()
+{
+ ErrorString error;
+ disable(&error);
+ DCHECK(m_frontend);
+ m_frontend = nullptr;
+}
+
+void V8HeapProfilerAgentImpl::restore()
+{
+ if (m_state->booleanProperty(HeapProfilerAgentState::heapProfilerEnabled, false))
+ m_frontend->resetProfiles();
+ if (m_state->booleanProperty(HeapProfilerAgentState::heapObjectsTrackingEnabled, false))
+ startTrackingHeapObjectsInternal(m_state->booleanProperty(HeapProfilerAgentState::allocationTrackingEnabled, false));
+#if V8_MAJOR_VERSION >= 5
+ if (m_state->booleanProperty(HeapProfilerAgentState::samplingHeapProfilerEnabled, false)) {
+ ErrorString error;
+ double samplingInterval = m_state->numberProperty(HeapProfilerAgentState::samplingHeapProfilerInterval, -1);
+ DCHECK_GE(samplingInterval, 0);
+ startSampling(&error, Maybe<double>(samplingInterval));
+ }
+#endif
+}
+
+void V8HeapProfilerAgentImpl::collectGarbage(ErrorString*)
+{
+ m_isolate->LowMemoryNotification();
+}
+
+void V8HeapProfilerAgentImpl::startTrackingHeapObjects(ErrorString*, const protocol::Maybe<bool>& trackAllocations)
+{
+ m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, true);
+ bool allocationTrackingEnabled = trackAllocations.fromMaybe(false);
+ m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled, allocationTrackingEnabled);
+ startTrackingHeapObjectsInternal(allocationTrackingEnabled);
+}
+
+void V8HeapProfilerAgentImpl::stopTrackingHeapObjects(ErrorString* error, const protocol::Maybe<bool>& reportProgress)
+{
+ requestHeapStatsUpdate();
+ takeHeapSnapshot(error, reportProgress);
+ stopTrackingHeapObjectsInternal();
+}
+
+void V8HeapProfilerAgentImpl::enable(ErrorString*)
+{
+ m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, true);
+}
+
+void V8HeapProfilerAgentImpl::disable(ErrorString* error)
+{
+ stopTrackingHeapObjectsInternal();
+#if V8_MAJOR_VERSION >= 5
+ if (m_state->booleanProperty(HeapProfilerAgentState::samplingHeapProfilerEnabled, false)) {
+ v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler();
+ if (profiler)
+ profiler->StopSamplingHeapProfiler();
+ }
+#endif
+ m_isolate->GetHeapProfiler()->ClearObjectIds();
+ m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, false);
+}
+
+void V8HeapProfilerAgentImpl::takeHeapSnapshot(ErrorString* errorString, const protocol::Maybe<bool>& reportProgress)
+{
+ v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler();
+ if (!profiler) {
+ *errorString = "Cannot access v8 heap profiler";
+ return;
+ }
+ std::unique_ptr<HeapSnapshotProgress> progress;
+ if (reportProgress.fromMaybe(false))
+ progress = wrapUnique(new HeapSnapshotProgress(m_frontend));
+
+ GlobalObjectNameResolver resolver(m_session);
+ const v8::HeapSnapshot* snapshot = profiler->TakeHeapSnapshot(progress.get(), &resolver);
+ if (!snapshot) {
+ *errorString = "Failed to take heap snapshot";
+ return;
+ }
+ HeapSnapshotOutputStream stream(m_frontend);
+ snapshot->Serialize(&stream);
+ const_cast<v8::HeapSnapshot*>(snapshot)->Delete();
+}
+
+void V8HeapProfilerAgentImpl::getObjectByHeapObjectId(ErrorString* error, const String16& heapSnapshotObjectId, const protocol::Maybe<String16>& objectGroup, std::unique_ptr<protocol::Runtime::RemoteObject>* result)
+{
+ bool ok;
+ int id = heapSnapshotObjectId.toInt(&ok);
+ if (!ok) {
+ *error = "Invalid heap snapshot object id";
+ return;
+ }
+
+ v8::HandleScope handles(m_isolate);
+ v8::Local<v8::Object> heapObject = objectByHeapObjectId(m_isolate, id);
+ if (heapObject.IsEmpty()) {
+ *error = "Object is not available";
+ return;
+ }
+
+ if (!m_session->debugger()->client()->isInspectableHeapObject(heapObject)) {
+ *error = "Object is not available";
+ return;
+ }
+
+ *result = m_session->wrapObject(heapObject->CreationContext(), heapObject, objectGroup.fromMaybe(""));
+ if (!result)
+ *error = "Object is not available";
+}
+
+void V8HeapProfilerAgentImpl::addInspectedHeapObject(ErrorString* errorString, const String16& inspectedHeapObjectId)
+{
+ bool ok;
+ int id = inspectedHeapObjectId.toInt(&ok);
+ if (!ok) {
+ *errorString = "Invalid heap snapshot object id";
+ return;
+ }
+
+ v8::HandleScope handles(m_isolate);
+ v8::Local<v8::Object> heapObject = objectByHeapObjectId(m_isolate, id);
+ if (heapObject.IsEmpty()) {
+ *errorString = "Object is not available";
+ return;
+ }
+
+ if (!m_session->debugger()->client()->isInspectableHeapObject(heapObject)) {
+ *errorString = "Object is not available";
+ return;
+ }
+
+ m_session->addInspectedObject(wrapUnique(new InspectableHeapObject(id)));
+}
+
+void V8HeapProfilerAgentImpl::getHeapObjectId(ErrorString* errorString, const String16& objectId, String16* heapSnapshotObjectId)
+{
+ v8::HandleScope handles(m_isolate);
+ v8::Local<v8::Value> value = m_session->findObject(errorString, objectId);
+ if (value.IsEmpty() || value->IsUndefined())
+ return;
+
+ v8::SnapshotObjectId id = m_isolate->GetHeapProfiler()->GetObjectId(value);
+ *heapSnapshotObjectId = String16::number(id);
+}
+
+void V8HeapProfilerAgentImpl::requestHeapStatsUpdate()
+{
+ if (!m_frontend)
+ return;
+ HeapStatsStream stream(m_frontend);
+ v8::SnapshotObjectId lastSeenObjectId = m_isolate->GetHeapProfiler()->GetHeapStats(&stream);
+ m_frontend->lastSeenObjectId(lastSeenObjectId, m_session->debugger()->client()->currentTimeMS());
+}
+
+// static
+void V8HeapProfilerAgentImpl::onTimer(void* data)
+{
+ reinterpret_cast<V8HeapProfilerAgentImpl*>(data)->requestHeapStatsUpdate();
+}
+
+void V8HeapProfilerAgentImpl::startTrackingHeapObjectsInternal(bool trackAllocations)
+{
+ m_isolate->GetHeapProfiler()->StartTrackingHeapObjects(trackAllocations);
+ if (!m_hasTimer) {
+ m_hasTimer = true;
+ m_session->debugger()->client()->startRepeatingTimer(0.05, &V8HeapProfilerAgentImpl::onTimer, reinterpret_cast<void*>(this));
+ }
+}
+
+void V8HeapProfilerAgentImpl::stopTrackingHeapObjectsInternal()
+{
+ if (m_hasTimer) {
+ m_session->debugger()->client()->cancelTimer(reinterpret_cast<void*>(this));
+ m_hasTimer = false;
+ }
+ m_isolate->GetHeapProfiler()->StopTrackingHeapObjects();
+ m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, false);
+ m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled, false);
+}
+
+void V8HeapProfilerAgentImpl::startSampling(ErrorString* errorString, const Maybe<double>& samplingInterval)
+{
+#if V8_MAJOR_VERSION >= 5
+ v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler();
+ if (!profiler) {
+ *errorString = "Cannot access v8 heap profiler";
+ return;
+ }
+ const unsigned defaultSamplingInterval = 1 << 15;
+ double samplingIntervalValue = samplingInterval.fromMaybe(defaultSamplingInterval);
+ m_state->setNumber(HeapProfilerAgentState::samplingHeapProfilerInterval, samplingIntervalValue);
+ m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled, true);
+#if V8_MAJOR_VERSION * 1000 + V8_MINOR_VERSION >= 5002
+ profiler->StartSamplingHeapProfiler(static_cast<uint64_t>(samplingIntervalValue), 128, v8::HeapProfiler::kSamplingForceGC);
+#else
+ profiler->StartSamplingHeapProfiler(static_cast<uint64_t>(samplingIntervalValue), 128);
+#endif
+#endif
+}
+
+#if V8_MAJOR_VERSION >= 5
+namespace {
+std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfileNode> buildSampingHeapProfileNode(const v8::AllocationProfile::Node* node)
+{
+ auto children = protocol::Array<protocol::HeapProfiler::SamplingHeapProfileNode>::create();
+ for (const auto* child : node->children)
+ children->addItem(buildSampingHeapProfileNode(child));
+ size_t selfSize = 0;
+ for (const auto& allocation : node->allocations)
+ selfSize += allocation.size * allocation.count;
+ std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfileNode> result = protocol::HeapProfiler::SamplingHeapProfileNode::create()
+ .setFunctionName(toProtocolString(node->name))
+ .setScriptId(String16::number(node->script_id))
+ .setUrl(toProtocolString(node->script_name))
+ .setLineNumber(node->line_number)
+ .setColumnNumber(node->column_number)
+ .setSelfSize(selfSize)
+ .setChildren(std::move(children)).build();
+ return result;
+}
+} // namespace
+#endif
+
+void V8HeapProfilerAgentImpl::stopSampling(ErrorString* errorString, std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfile>* profile)
+{
+#if V8_MAJOR_VERSION >= 5
+ v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler();
+ if (!profiler) {
+ *errorString = "Cannot access v8 heap profiler";
+ return;
+ }
+ v8::HandleScope scope(m_isolate); // Allocation profile contains Local handles.
+ std::unique_ptr<v8::AllocationProfile> v8Profile(profiler->GetAllocationProfile());
+ profiler->StopSamplingHeapProfiler();
+ m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled, false);
+ if (!v8Profile) {
+ *errorString = "Cannot access v8 sampled heap profile.";
+ return;
+ }
+ v8::AllocationProfile::Node* root = v8Profile->GetRootNode();
+ *profile = protocol::HeapProfiler::SamplingHeapProfile::create()
+ .setHead(buildSampingHeapProfileNode(root)).build();
+#endif
+}
+
+} // namespace blink
diff --git a/deps/v8_inspector/platform/v8_inspector/V8HeapProfilerAgentImpl.h b/deps/v8_inspector/platform/v8_inspector/V8HeapProfilerAgentImpl.h
new file mode 100644
index 0000000000..082e533d60
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8HeapProfilerAgentImpl.h
@@ -0,0 +1,60 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8HeapProfilerAgentImpl_h
+#define V8HeapProfilerAgentImpl_h
+
+#include "platform/inspector_protocol/Allocator.h"
+#include "platform/v8_inspector/public/V8HeapProfilerAgent.h"
+
+namespace blink {
+
+class V8InspectorSessionImpl;
+
+using protocol::Maybe;
+
+class V8HeapProfilerAgentImpl : public V8HeapProfilerAgent {
+ PROTOCOL_DISALLOW_COPY(V8HeapProfilerAgentImpl);
+public:
+ explicit V8HeapProfilerAgentImpl(V8InspectorSessionImpl*);
+ ~V8HeapProfilerAgentImpl() override;
+
+ void setInspectorState(protocol::DictionaryValue* state) override { m_state = state; }
+ void setFrontend(protocol::Frontend::HeapProfiler* frontend) override { m_frontend = frontend; }
+ void clearFrontend() override;
+ void restore() override;
+
+ void collectGarbage(ErrorString*) override;
+
+ void enable(ErrorString*) override;
+ void startTrackingHeapObjects(ErrorString*, const Maybe<bool>& trackAllocations) override;
+ void stopTrackingHeapObjects(ErrorString*, const Maybe<bool>& reportProgress) override;
+
+ void disable(ErrorString*) override;
+
+ void takeHeapSnapshot(ErrorString*, const Maybe<bool>& reportProgress) override;
+
+ void getObjectByHeapObjectId(ErrorString*, const String16& heapSnapshotObjectId, const Maybe<String16>& objectGroup, std::unique_ptr<protocol::Runtime::RemoteObject>* result) override;
+ void addInspectedHeapObject(ErrorString*, const String16& inspectedHeapObjectId) override;
+ void getHeapObjectId(ErrorString*, const String16& objectId, String16* heapSnapshotObjectId) override;
+
+ void startSampling(ErrorString*, const Maybe<double>& samplingInterval) override;
+ void stopSampling(ErrorString*, std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfile>*) override;
+
+private:
+ void startTrackingHeapObjectsInternal(bool trackAllocations);
+ void stopTrackingHeapObjectsInternal();
+ void requestHeapStatsUpdate();
+ static void onTimer(void*);
+
+ V8InspectorSessionImpl* m_session;
+ v8::Isolate* m_isolate;
+ protocol::Frontend::HeapProfiler* m_frontend;
+ protocol::DictionaryValue* m_state;
+ bool m_hasTimer;
+};
+
+} // namespace blink
+
+#endif // !defined(V8HeapProfilerAgentImpl_h)
diff --git a/deps/v8_inspector/platform/v8_inspector/V8InjectedScriptHost.cpp b/deps/v8_inspector/platform/v8_inspector/V8InjectedScriptHost.cpp
new file mode 100644
index 0000000000..e25431f3cb
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8InjectedScriptHost.cpp
@@ -0,0 +1,286 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/v8_inspector/V8InjectedScriptHost.h"
+
+#include "platform/inspector_protocol/String16.h"
+#include "platform/v8_inspector/InjectedScriptNative.h"
+#include "platform/v8_inspector/V8Compat.h"
+#include "platform/v8_inspector/V8DebuggerImpl.h"
+#include "platform/v8_inspector/V8StringUtil.h"
+#include "platform/v8_inspector/public/V8DebuggerClient.h"
+#include "platform/v8_inspector/public/V8EventListenerInfo.h"
+
+namespace blink {
+
+namespace {
+
+void setFunctionProperty(v8::Local<v8::Context> context, v8::Local<v8::Object> obj, const char* name, v8::FunctionCallback callback, v8::Local<v8::External> external)
+{
+ v8::Local<v8::String> funcName = toV8StringInternalized(context->GetIsolate(), name);
+ v8::Local<v8::Function> func;
+ if (!v8::Function::New(context, callback, external).ToLocal(&func))
+ return;
+ func->SetName(funcName);
+ if (!obj->Set(context, funcName, func).FromMaybe(false))
+ return;
+}
+
+V8DebuggerImpl* unwrapDebugger(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ DCHECK(!info.Data().IsEmpty());
+ DCHECK(info.Data()->IsExternal());
+ V8DebuggerImpl* debugger = static_cast<V8DebuggerImpl*>(info.Data().As<v8::External>()->Value());
+ DCHECK(debugger);
+ return debugger;
+}
+
+} // namespace
+
+v8::Local<v8::Object> V8InjectedScriptHost::create(v8::Local<v8::Context> context, V8DebuggerImpl* debugger)
+{
+ v8::Isolate* isolate = debugger->isolate();
+ v8::Local<v8::Object> injectedScriptHost = v8::Object::New(isolate);
+ v8::Local<v8::External> debuggerExternal = v8::External::New(isolate, debugger);
+ setFunctionProperty(context, injectedScriptHost, "internalConstructorName", V8InjectedScriptHost::internalConstructorNameCallback, debuggerExternal);
+ setFunctionProperty(context, injectedScriptHost, "formatAccessorsAsProperties", V8InjectedScriptHost::formatAccessorsAsProperties, debuggerExternal);
+ setFunctionProperty(context, injectedScriptHost, "isTypedArray", V8InjectedScriptHost::isTypedArrayCallback, debuggerExternal);
+ setFunctionProperty(context, injectedScriptHost, "subtype", V8InjectedScriptHost::subtypeCallback, debuggerExternal);
+ setFunctionProperty(context, injectedScriptHost, "collectionEntries", V8InjectedScriptHost::collectionEntriesCallback, debuggerExternal);
+ setFunctionProperty(context, injectedScriptHost, "getInternalProperties", V8InjectedScriptHost::getInternalPropertiesCallback, debuggerExternal);
+ setFunctionProperty(context, injectedScriptHost, "getEventListeners", V8InjectedScriptHost::getEventListenersCallback, debuggerExternal);
+ setFunctionProperty(context, injectedScriptHost, "suppressWarningsAndCallFunction", V8InjectedScriptHost::suppressWarningsAndCallFunctionCallback, debuggerExternal);
+ setFunctionProperty(context, injectedScriptHost, "setNonEnumProperty", V8InjectedScriptHost::setNonEnumPropertyCallback, debuggerExternal);
+ setFunctionProperty(context, injectedScriptHost, "bind", V8InjectedScriptHost::bindCallback, debuggerExternal);
+ setFunctionProperty(context, injectedScriptHost, "proxyTargetValue", V8InjectedScriptHost::proxyTargetValueCallback, debuggerExternal);
+ setFunctionProperty(context, injectedScriptHost, "prototype", V8InjectedScriptHost::prototypeCallback, debuggerExternal);
+ return injectedScriptHost;
+}
+
+void V8InjectedScriptHost::internalConstructorNameCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ if (info.Length() < 1 || !info[0]->IsObject())
+ return;
+
+ v8::Local<v8::Object> object = info[0].As<v8::Object>();
+ info.GetReturnValue().Set(object->GetConstructorName());
+}
+
+void V8InjectedScriptHost::formatAccessorsAsProperties(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ if (info.Length() < 1)
+ return;
+
+ info.GetReturnValue().Set(unwrapDebugger(info)->client()->formatAccessorsAsProperties(info[0]));
+}
+
+void V8InjectedScriptHost::isTypedArrayCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ if (info.Length() < 1)
+ return;
+
+ info.GetReturnValue().Set(info[0]->IsTypedArray());
+}
+
+void V8InjectedScriptHost::subtypeCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ if (info.Length() < 1)
+ return;
+
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Value> value = info[0];
+ if (value->IsArray() || value->IsTypedArray() || value->IsArgumentsObject()) {
+ info.GetReturnValue().Set(toV8StringInternalized(isolate, "array"));
+ return;
+ }
+ if (value->IsDate()) {
+ info.GetReturnValue().Set(toV8StringInternalized(isolate, "date"));
+ return;
+ }
+ if (value->IsRegExp()) {
+ info.GetReturnValue().Set(toV8StringInternalized(isolate, "regexp"));
+ return;
+ }
+ if (value->IsMap() || value->IsWeakMap()) {
+ info.GetReturnValue().Set(toV8StringInternalized(isolate, "map"));
+ return;
+ }
+ if (value->IsSet() || value->IsWeakSet()) {
+ info.GetReturnValue().Set(toV8StringInternalized(isolate, "set"));
+ return;
+ }
+ if (value->IsMapIterator() || value->IsSetIterator()) {
+ info.GetReturnValue().Set(toV8StringInternalized(isolate, "iterator"));
+ return;
+ }
+ if (value->IsGeneratorObject()) {
+ info.GetReturnValue().Set(toV8StringInternalized(isolate, "generator"));
+ return;
+ }
+ if (value->IsNativeError()) {
+ info.GetReturnValue().Set(toV8StringInternalized(isolate, "error"));
+ return;
+ }
+ if (value->IsProxy()) {
+ info.GetReturnValue().Set(toV8StringInternalized(isolate, "proxy"));
+ return;
+ }
+ String16 subtype = unwrapDebugger(info)->client()->valueSubtype(value);
+ if (!subtype.isEmpty()) {
+ info.GetReturnValue().Set(toV8String(isolate, subtype));
+ return;
+ }
+}
+
+void V8InjectedScriptHost::collectionEntriesCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ if (info.Length() < 1 || !info[0]->IsObject())
+ return;
+
+ v8::Local<v8::Object> object = info[0].As<v8::Object>();
+ info.GetReturnValue().Set(unwrapDebugger(info)->collectionEntries(object));
+}
+
+void V8InjectedScriptHost::getInternalPropertiesCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ if (info.Length() < 1 || !info[0]->IsObject())
+ return;
+
+ v8::Local<v8::Object> object = info[0].As<v8::Object>();
+ v8::Local<v8::Array> properties;
+ if (v8::Debug::GetInternalProperties(info.GetIsolate(), object).ToLocal(&properties))
+ info.GetReturnValue().Set(properties);
+}
+
+static v8::Local<v8::Array> wrapListenerFunctions(v8::Isolate* isolate, const V8EventListenerInfoList& listeners, const String16& type)
+{
+ v8::Local<v8::Array> result = v8::Array::New(isolate);
+ size_t handlersCount = listeners.size();
+ for (size_t i = 0, outputIndex = 0; i < handlersCount; ++i) {
+ if (listeners[i].eventType != type)
+ continue;
+ v8::Local<v8::Object> function = listeners[i].handler;
+ v8::Local<v8::Object> listenerEntry = v8::Object::New(isolate);
+ listenerEntry->Set(toV8StringInternalized(isolate, "listener"), function);
+ listenerEntry->Set(toV8StringInternalized(isolate, "useCapture"), v8::Boolean::New(isolate, listeners[i].useCapture));
+ listenerEntry->Set(toV8StringInternalized(isolate, "passive"), v8::Boolean::New(isolate, listeners[i].passive));
+ result->Set(v8::Number::New(isolate, outputIndex++), listenerEntry);
+ }
+ return result;
+}
+
+void V8InjectedScriptHost::getEventListenersCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ if (info.Length() < 1)
+ return;
+
+ V8DebuggerClient* client = unwrapDebugger(info)->client();
+ V8EventListenerInfoList listenerInfo;
+ // eventListeners call can produce message on ErrorEvent during lazy event listener compilation.
+ client->muteWarningsAndDeprecations();
+ client->eventListeners(info[0], listenerInfo);
+ client->unmuteWarningsAndDeprecations();
+
+ v8::Local<v8::Object> result = v8::Object::New(info.GetIsolate());
+ protocol::HashSet<String16> types;
+ for (auto& info : listenerInfo)
+ types.add(info.eventType);
+ for (const auto& it : types) {
+ v8::Local<v8::Array> listeners = wrapListenerFunctions(info.GetIsolate(), listenerInfo, it.first);
+ if (!listeners->Length())
+ continue;
+ result->Set(toV8String(info.GetIsolate(), it.first), listeners);
+ }
+ info.GetReturnValue().Set(result);
+}
+
+void V8InjectedScriptHost::suppressWarningsAndCallFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ if (info.Length() < 2 || info.Length() > 3 || !info[0]->IsFunction()) {
+ NOTREACHED();
+ return;
+ }
+ if (info.Length() > 2 && (!info[2]->IsArray() && !info[2]->IsUndefined())) {
+ NOTREACHED();
+ return;
+ }
+
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Context> context = isolate->GetCurrentContext();
+
+ v8::Local<v8::Function> function = info[0].As<v8::Function>();
+ v8::Local<v8::Value> receiver = info[1];
+ std::unique_ptr<v8::Local<v8::Value>[]> argv = nullptr;
+ size_t argc = 0;
+
+ if (info.Length() > 2 && info[2]->IsArray()) {
+ v8::Local<v8::Array> arguments = info[2].As<v8::Array>();
+ argc = arguments->Length();
+ argv.reset(new v8::Local<v8::Value>[argc]);
+ for (size_t i = 0; i < argc; ++i) {
+ if (!arguments->Get(context, i).ToLocal(&argv[i]))
+ return;
+ }
+ }
+
+ V8DebuggerClient* client = unwrapDebugger(info)->client();
+ client->muteWarningsAndDeprecations();
+
+ v8::MicrotasksScope microtasks(isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
+ v8::Local<v8::Value> result;
+ if (function->Call(context, receiver, argc, argv.get()).ToLocal(&result))
+ info.GetReturnValue().Set(result);
+
+ client->unmuteWarningsAndDeprecations();
+}
+
+void V8InjectedScriptHost::setNonEnumPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ if (info.Length() < 3 || !info[0]->IsObject() || !info[1]->IsString())
+ return;
+
+ v8::Local<v8::Object> object = info[0].As<v8::Object>();
+ v8::Maybe<bool> success = object->DefineOwnProperty(info.GetIsolate()->GetCurrentContext(), info[1].As<v8::String>(), info[2], v8::DontEnum);
+ USE(success);
+ DCHECK(!success.IsNothing());
+}
+
+void V8InjectedScriptHost::bindCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ if (info.Length() < 2 || !info[1]->IsString())
+ return;
+ InjectedScriptNative* injectedScriptNative = InjectedScriptNative::fromInjectedScriptHost(info.Holder());
+ if (!injectedScriptNative)
+ return;
+
+ v8::Local<v8::String> v8groupName = info[1]->ToString(info.GetIsolate());
+ String16 groupName = toProtocolStringWithTypeCheck(v8groupName);
+ int id = injectedScriptNative->bind(info[0], groupName);
+ info.GetReturnValue().Set(id);
+}
+
+void V8InjectedScriptHost::proxyTargetValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ if (info.Length() != 1 || !info[0]->IsProxy()) {
+ NOTREACHED();
+ return;
+ }
+ v8::Local<v8::Object> target = info[0].As<v8::Proxy>();
+ while (target->IsProxy())
+ target = v8::Local<v8::Proxy>::Cast(target)->GetTarget();
+ info.GetReturnValue().Set(target);
+}
+
+void V8InjectedScriptHost::prototypeCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ DCHECK(info.Length() > 0 && info[0]->IsObject());
+ info.GetReturnValue().Set(info[0].As<v8::Object>()->GetPrototype());
+}
+
+v8::Local<v8::Private> V8Debugger::scopeExtensionPrivate(v8::Isolate* isolate)
+{
+ return v8::Private::ForApi(isolate, toV8StringInternalized(isolate, "V8Debugger#scopeExtension"));
+}
+
+} // namespace blink
diff --git a/deps/v8_inspector/platform/v8_inspector/V8InjectedScriptHost.h b/deps/v8_inspector/platform/v8_inspector/V8InjectedScriptHost.h
new file mode 100644
index 0000000000..a05dd29cee
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8InjectedScriptHost.h
@@ -0,0 +1,44 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8InjectedScriptHost_h
+#define V8InjectedScriptHost_h
+
+#include <v8.h>
+
+namespace blink {
+
+class V8DebuggerImpl;
+
+// SECURITY NOTE: Although the InjectedScriptHost is intended for use solely by the inspector,
+// a reference to the InjectedScriptHost may be leaked to the page being inspected. Thus, the
+// InjectedScriptHost must never implemment methods that have more power over the page than the
+// page already has itself (e.g. origin restriction bypasses).
+
+class V8InjectedScriptHost {
+public:
+ // We expect that debugger outlives any JS context and thus V8InjectedScriptHost (owned by JS)
+ // is destroyed before debugger.
+ static v8::Local<v8::Object> create(v8::Local<v8::Context>, V8DebuggerImpl*);
+
+private:
+ static void internalConstructorNameCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void formatAccessorsAsProperties(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void isTypedArrayCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void subtypeCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void generatorObjectDetailsCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void collectionEntriesCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void getInternalPropertiesCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void getEventListenersCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void suppressWarningsAndCallFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void setNonEnumPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void setFunctionVariableValueCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void bindCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void proxyTargetValueCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ static void prototypeCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+};
+
+} // namespace blink
+
+#endif // V8InjectedScriptHost_h
diff --git a/deps/v8_inspector/platform/v8_inspector/V8InspectorSessionImpl.cpp b/deps/v8_inspector/platform/v8_inspector/V8InspectorSessionImpl.cpp
new file mode 100644
index 0000000000..6453ce649e
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8InspectorSessionImpl.cpp
@@ -0,0 +1,279 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/v8_inspector/V8InspectorSessionImpl.h"
+
+#include "platform/v8_inspector/InjectedScript.h"
+#include "platform/v8_inspector/InspectedContext.h"
+#include "platform/v8_inspector/RemoteObjectId.h"
+#include "platform/v8_inspector/V8DebuggerAgentImpl.h"
+#include "platform/v8_inspector/V8DebuggerImpl.h"
+#include "platform/v8_inspector/V8HeapProfilerAgentImpl.h"
+#include "platform/v8_inspector/V8ProfilerAgentImpl.h"
+#include "platform/v8_inspector/V8RuntimeAgentImpl.h"
+#include "platform/v8_inspector/public/V8ContextInfo.h"
+#include "platform/v8_inspector/public/V8DebuggerClient.h"
+
+namespace blink {
+
+const char V8InspectorSession::backtraceObjectGroup[] = "backtrace";
+
+std::unique_ptr<V8InspectorSessionImpl> V8InspectorSessionImpl::create(V8DebuggerImpl* debugger, int contextGroupId)
+{
+ return wrapUnique(new V8InspectorSessionImpl(debugger, contextGroupId));
+}
+
+V8InspectorSessionImpl::V8InspectorSessionImpl(V8DebuggerImpl* debugger, int contextGroupId)
+ : m_contextGroupId(contextGroupId)
+ , m_debugger(debugger)
+ , m_client(nullptr)
+ , m_customObjectFormatterEnabled(false)
+ , m_instrumentationCounter(0)
+ , m_runtimeAgent(wrapUnique(new V8RuntimeAgentImpl(this)))
+ , m_debuggerAgent(wrapUnique(new V8DebuggerAgentImpl(this)))
+ , m_heapProfilerAgent(wrapUnique(new V8HeapProfilerAgentImpl(this)))
+ , m_profilerAgent(wrapUnique(new V8ProfilerAgentImpl(this)))
+{
+}
+
+V8InspectorSessionImpl::~V8InspectorSessionImpl()
+{
+ discardInjectedScripts();
+ m_debugger->disconnect(this);
+}
+
+V8DebuggerAgent* V8InspectorSessionImpl::debuggerAgent()
+{
+ return m_debuggerAgent.get();
+}
+
+V8HeapProfilerAgent* V8InspectorSessionImpl::heapProfilerAgent()
+{
+ return m_heapProfilerAgent.get();
+}
+
+V8ProfilerAgent* V8InspectorSessionImpl::profilerAgent()
+{
+ return m_profilerAgent.get();
+}
+
+V8RuntimeAgent* V8InspectorSessionImpl::runtimeAgent()
+{
+ return m_runtimeAgent.get();
+}
+
+void V8InspectorSessionImpl::setClient(V8InspectorSessionClient* client)
+{
+ m_client = client;
+}
+
+void V8InspectorSessionImpl::reset()
+{
+ m_debuggerAgent->reset();
+ m_runtimeAgent->reset();
+ discardInjectedScripts();
+}
+
+void V8InspectorSessionImpl::discardInjectedScripts()
+{
+ m_inspectedObjects.clear();
+ const V8DebuggerImpl::ContextByIdMap* contexts = m_debugger->contextGroup(m_contextGroupId);
+ if (!contexts)
+ return;
+
+ protocol::Vector<int> keys;
+ for (auto& idContext : *contexts)
+ keys.append(idContext.first);
+ for (auto& key : keys) {
+ contexts = m_debugger->contextGroup(m_contextGroupId);
+ if (contexts && contexts->contains(key))
+ contexts->get(key)->discardInjectedScript(); // This may destroy some contexts.
+ }
+}
+
+InjectedScript* V8InspectorSessionImpl::findInjectedScript(ErrorString* errorString, int contextId)
+{
+ if (!contextId) {
+ *errorString = "Cannot find context with specified id";
+ return nullptr;
+ }
+
+ const V8DebuggerImpl::ContextByIdMap* contexts = m_debugger->contextGroup(m_contextGroupId);
+ if (!contexts || !contexts->contains(contextId)) {
+ *errorString = "Cannot find context with specified id";
+ return nullptr;
+ }
+
+ InspectedContext* context = contexts->get(contextId);
+ if (!context->getInjectedScript()) {
+ context->createInjectedScript();
+ if (!context->getInjectedScript()) {
+ *errorString = "Cannot access specified execution context";
+ return nullptr;
+ }
+ if (m_customObjectFormatterEnabled)
+ context->getInjectedScript()->setCustomObjectFormatterEnabled(true);
+ }
+ return context->getInjectedScript();
+}
+
+InjectedScript* V8InspectorSessionImpl::findInjectedScript(ErrorString* errorString, RemoteObjectIdBase* objectId)
+{
+ return objectId ? findInjectedScript(errorString, objectId->contextId()) : nullptr;
+}
+
+void V8InspectorSessionImpl::releaseObjectGroup(const String16& objectGroup)
+{
+ const V8DebuggerImpl::ContextByIdMap* contexts = m_debugger->contextGroup(m_contextGroupId);
+ if (!contexts)
+ return;
+
+ protocol::Vector<int> keys;
+ for (auto& idContext : *contexts)
+ keys.append(idContext.first);
+ for (auto& key : keys) {
+ contexts = m_debugger->contextGroup(m_contextGroupId);
+ if (contexts && contexts->contains(key)) {
+ InjectedScript* injectedScript = contexts->get(key)->getInjectedScript();
+ if (injectedScript)
+ injectedScript->releaseObjectGroup(objectGroup); // This may destroy some contexts.
+ }
+ }
+}
+
+v8::Local<v8::Value> V8InspectorSessionImpl::findObject(ErrorString* errorString, const String16& objectId, v8::Local<v8::Context>* context, String16* groupName)
+{
+ std::unique_ptr<RemoteObjectId> remoteId = RemoteObjectId::parse(errorString, objectId);
+ if (!remoteId)
+ return v8::Local<v8::Value>();
+ InjectedScript* injectedScript = findInjectedScript(errorString, remoteId.get());
+ if (!injectedScript)
+ return v8::Local<v8::Value>();
+ v8::Local<v8::Value> objectValue;
+ injectedScript->findObject(errorString, *remoteId, &objectValue);
+ if (objectValue.IsEmpty())
+ return v8::Local<v8::Value>();
+ if (context)
+ *context = injectedScript->context()->context();
+ if (groupName)
+ *groupName = injectedScript->objectGroupName(*remoteId);
+ return objectValue;
+}
+
+std::unique_ptr<protocol::Runtime::RemoteObject> V8InspectorSessionImpl::wrapObject(v8::Local<v8::Context> context, v8::Local<v8::Value> value, const String16& groupName, bool generatePreview)
+{
+ ErrorString errorString;
+ InjectedScript* injectedScript = findInjectedScript(&errorString, V8Debugger::contextId(context));
+ if (!injectedScript)
+ return nullptr;
+ return injectedScript->wrapObject(&errorString, value, groupName, false, generatePreview);
+}
+
+std::unique_ptr<protocol::Runtime::RemoteObject> V8InspectorSessionImpl::wrapTable(v8::Local<v8::Context> context, v8::Local<v8::Value> table, v8::Local<v8::Value> columns)
+{
+ ErrorString errorString;
+ InjectedScript* injectedScript = findInjectedScript(&errorString, V8Debugger::contextId(context));
+ if (!injectedScript)
+ return nullptr;
+ return injectedScript->wrapTable(table, columns);
+}
+
+void V8InspectorSessionImpl::setCustomObjectFormatterEnabled(bool enabled)
+{
+ m_customObjectFormatterEnabled = enabled;
+ const V8DebuggerImpl::ContextByIdMap* contexts = m_debugger->contextGroup(m_contextGroupId);
+ if (!contexts)
+ return;
+ for (auto& idContext : *contexts) {
+ InjectedScript* injectedScript = idContext.second->getInjectedScript();
+ if (injectedScript)
+ injectedScript->setCustomObjectFormatterEnabled(enabled);
+ }
+}
+
+void V8InspectorSessionImpl::reportAllContexts(V8RuntimeAgentImpl* agent)
+{
+ const V8DebuggerImpl::ContextByIdMap* contexts = m_debugger->contextGroup(m_contextGroupId);
+ if (!contexts)
+ return;
+ for (auto& idContext : *contexts)
+ agent->reportExecutionContextCreated(idContext.second);
+}
+
+void V8InspectorSessionImpl::changeInstrumentationCounter(int delta)
+{
+ DCHECK(m_instrumentationCounter + delta >= 0);
+ if (!m_instrumentationCounter && m_client)
+ m_client->startInstrumenting();
+ m_instrumentationCounter += delta;
+ if (!m_instrumentationCounter && m_client)
+ m_client->stopInstrumenting();
+}
+
+void V8InspectorSessionImpl::addInspectedObject(std::unique_ptr<V8InspectorSession::Inspectable> inspectable)
+{
+ m_inspectedObjects.prepend(std::move(inspectable));
+ while (m_inspectedObjects.size() > kInspectedObjectBufferSize)
+ m_inspectedObjects.removeLast();
+}
+
+V8InspectorSession::Inspectable* V8InspectorSessionImpl::inspectedObject(unsigned num)
+{
+ if (num >= m_inspectedObjects.size())
+ return nullptr;
+ return m_inspectedObjects[num];
+}
+
+void V8InspectorSessionImpl::schedulePauseOnNextStatement(const String16& breakReason, std::unique_ptr<protocol::DictionaryValue> data)
+{
+ m_debuggerAgent->schedulePauseOnNextStatement(breakReason, std::move(data));
+}
+
+void V8InspectorSessionImpl::cancelPauseOnNextStatement()
+{
+ m_debuggerAgent->cancelPauseOnNextStatement();
+}
+
+void V8InspectorSessionImpl::breakProgram(const String16& breakReason, std::unique_ptr<protocol::DictionaryValue> data)
+{
+ m_debuggerAgent->breakProgram(breakReason, std::move(data));
+}
+
+void V8InspectorSessionImpl::breakProgramOnException(const String16& breakReason, std::unique_ptr<protocol::DictionaryValue> data)
+{
+ m_debuggerAgent->breakProgramOnException(breakReason, std::move(data));
+}
+
+void V8InspectorSessionImpl::setSkipAllPauses(bool skip)
+{
+ ErrorString errorString;
+ m_debuggerAgent->setSkipAllPauses(&errorString, skip);
+}
+
+void V8InspectorSessionImpl::asyncTaskScheduled(const String16& taskName, void* task, bool recurring)
+{
+ m_debuggerAgent->asyncTaskScheduled(taskName, task, recurring);
+}
+
+void V8InspectorSessionImpl::asyncTaskCanceled(void* task)
+{
+ m_debuggerAgent->asyncTaskCanceled(task);
+}
+
+void V8InspectorSessionImpl::asyncTaskStarted(void* task)
+{
+ m_debuggerAgent->asyncTaskStarted(task);
+}
+
+void V8InspectorSessionImpl::asyncTaskFinished(void* task)
+{
+ m_debuggerAgent->asyncTaskFinished(task);
+}
+
+void V8InspectorSessionImpl::allAsyncTasksCanceled()
+{
+ m_debuggerAgent->allAsyncTasksCanceled();
+}
+
+} // namespace blink
diff --git a/deps/v8_inspector/platform/v8_inspector/V8InspectorSessionImpl.h b/deps/v8_inspector/platform/v8_inspector/V8InspectorSessionImpl.h
new file mode 100644
index 0000000000..ecc1087605
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8InspectorSessionImpl.h
@@ -0,0 +1,93 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8InspectorSessionImpl_h
+#define V8InspectorSessionImpl_h
+
+#include "platform/inspector_protocol/Allocator.h"
+#include "platform/inspector_protocol/Collections.h"
+#include "platform/inspector_protocol/String16.h"
+#include "platform/inspector_protocol/TypeBuilder.h"
+#include "platform/v8_inspector/public/V8InspectorSession.h"
+#include "platform/v8_inspector/public/V8InspectorSessionClient.h"
+#include "platform/v8_inspector/public/V8RuntimeAgent.h"
+#include "wtf/PtrUtil.h"
+
+#include <v8.h>
+
+namespace blink {
+
+class InjectedScript;
+class RemoteObjectIdBase;
+class V8DebuggerAgentImpl;
+class V8DebuggerImpl;
+class V8HeapProfilerAgentImpl;
+class V8ProfilerAgentImpl;
+class V8RuntimeAgentImpl;
+
+class V8InspectorSessionImpl : public V8InspectorSession {
+ PROTOCOL_DISALLOW_COPY(V8InspectorSessionImpl);
+public:
+ static std::unique_ptr<V8InspectorSessionImpl> create(V8DebuggerImpl*, int contextGroupId);
+ ~V8InspectorSessionImpl();
+
+ V8DebuggerImpl* debugger() const { return m_debugger; }
+ V8InspectorSessionClient* client() const { return m_client; }
+ V8DebuggerAgentImpl* debuggerAgentImpl() { return m_debuggerAgent.get(); }
+ V8ProfilerAgentImpl* profilerAgentImpl() { return m_profilerAgent.get(); }
+ V8RuntimeAgentImpl* runtimeAgentImpl() { return m_runtimeAgent.get(); }
+ int contextGroupId() const { return m_contextGroupId; }
+
+ InjectedScript* findInjectedScript(ErrorString*, int contextId);
+ InjectedScript* findInjectedScript(ErrorString*, RemoteObjectIdBase*);
+ void reset();
+ void discardInjectedScripts();
+ void reportAllContexts(V8RuntimeAgentImpl*);
+ void setCustomObjectFormatterEnabled(bool);
+ void changeInstrumentationCounter(int delta);
+
+ // V8InspectorSession implementation.
+ void setClient(V8InspectorSessionClient*) override;
+ void addInspectedObject(std::unique_ptr<V8InspectorSession::Inspectable>) override;
+ V8DebuggerAgent* debuggerAgent() override;
+ V8HeapProfilerAgent* heapProfilerAgent() override;
+ V8ProfilerAgent* profilerAgent() override;
+ V8RuntimeAgent* runtimeAgent() override;
+ void schedulePauseOnNextStatement(const String16& breakReason, std::unique_ptr<protocol::DictionaryValue> data) override;
+ void cancelPauseOnNextStatement() override;
+ void breakProgram(const String16& breakReason, std::unique_ptr<protocol::DictionaryValue> data) override;
+ void breakProgramOnException(const String16& breakReason, std::unique_ptr<protocol::DictionaryValue> data) override;
+ void setSkipAllPauses(bool) override;
+ void asyncTaskScheduled(const String16& taskName, void* task, bool recurring) override;
+ void asyncTaskCanceled(void* task) override;
+ void asyncTaskStarted(void* task) override;
+ void asyncTaskFinished(void* task) override;
+ void allAsyncTasksCanceled() override;
+ void releaseObjectGroup(const String16& objectGroup) override;
+ v8::Local<v8::Value> findObject(ErrorString*, const String16& objectId, v8::Local<v8::Context>* = nullptr, String16* groupName = nullptr) override;
+ std::unique_ptr<protocol::Runtime::RemoteObject> wrapObject(v8::Local<v8::Context>, v8::Local<v8::Value>, const String16& groupName, bool generatePreview = false) override;
+ std::unique_ptr<protocol::Runtime::RemoteObject> wrapTable(v8::Local<v8::Context>, v8::Local<v8::Value> table, v8::Local<v8::Value> columns) override;
+
+ V8InspectorSession::Inspectable* inspectedObject(unsigned num);
+ static const unsigned kInspectedObjectBufferSize = 5;
+
+private:
+ V8InspectorSessionImpl(V8DebuggerImpl*, int contextGroupId);
+
+ int m_contextGroupId;
+ V8DebuggerImpl* m_debugger;
+ V8InspectorSessionClient* m_client;
+ bool m_customObjectFormatterEnabled;
+ int m_instrumentationCounter;
+
+ std::unique_ptr<V8RuntimeAgentImpl> m_runtimeAgent;
+ std::unique_ptr<V8DebuggerAgentImpl> m_debuggerAgent;
+ std::unique_ptr<V8HeapProfilerAgentImpl> m_heapProfilerAgent;
+ std::unique_ptr<V8ProfilerAgentImpl> m_profilerAgent;
+ protocol::Vector<std::unique_ptr<V8InspectorSession::Inspectable>> m_inspectedObjects;
+};
+
+} // namespace blink
+
+#endif
diff --git a/deps/v8_inspector/platform/v8_inspector/V8ProfilerAgentImpl.cpp b/deps/v8_inspector/platform/v8_inspector/V8ProfilerAgentImpl.cpp
new file mode 100644
index 0000000000..dd5c2e5825
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8ProfilerAgentImpl.cpp
@@ -0,0 +1,302 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/v8_inspector/V8ProfilerAgentImpl.h"
+
+#include "platform/v8_inspector/Atomics.h"
+#include "platform/v8_inspector/V8DebuggerImpl.h"
+#include "platform/v8_inspector/V8InspectorSessionImpl.h"
+#include "platform/v8_inspector/V8StackTraceImpl.h"
+#include "platform/v8_inspector/V8StringUtil.h"
+#include <v8-profiler.h>
+
+namespace blink {
+
+namespace ProfilerAgentState {
+static const char samplingInterval[] = "samplingInterval";
+static const char userInitiatedProfiling[] = "userInitiatedProfiling";
+static const char profilerEnabled[] = "profilerEnabled";
+}
+
+namespace {
+
+std::unique_ptr<protocol::Array<protocol::Profiler::PositionTickInfo>> buildInspectorObjectForPositionTicks(const v8::CpuProfileNode* node)
+{
+ std::unique_ptr<protocol::Array<protocol::Profiler::PositionTickInfo>> array = protocol::Array<protocol::Profiler::PositionTickInfo>::create();
+ unsigned lineCount = node->GetHitLineCount();
+ if (!lineCount)
+ return array;
+
+ protocol::Vector<v8::CpuProfileNode::LineTick> entries(lineCount);
+ if (node->GetLineTicks(&entries[0], lineCount)) {
+ for (unsigned i = 0; i < lineCount; i++) {
+ std::unique_ptr<protocol::Profiler::PositionTickInfo> line = protocol::Profiler::PositionTickInfo::create()
+ .setLine(entries[i].line)
+ .setTicks(entries[i].hit_count).build();
+ array->addItem(std::move(line));
+ }
+ }
+
+ return array;
+}
+
+std::unique_ptr<protocol::Profiler::CPUProfileNode> buildInspectorObjectFor(v8::Isolate* isolate, const v8::CpuProfileNode* node)
+{
+ v8::HandleScope handleScope(isolate);
+
+ std::unique_ptr<protocol::Array<protocol::Profiler::CPUProfileNode>> children = protocol::Array<protocol::Profiler::CPUProfileNode>::create();
+ const int childrenCount = node->GetChildrenCount();
+ for (int i = 0; i < childrenCount; i++) {
+ const v8::CpuProfileNode* child = node->GetChild(i);
+ children->addItem(buildInspectorObjectFor(isolate, child));
+ }
+
+ std::unique_ptr<protocol::Array<protocol::Profiler::PositionTickInfo>> positionTicks = buildInspectorObjectForPositionTicks(node);
+
+ std::unique_ptr<protocol::Profiler::CPUProfileNode> result = protocol::Profiler::CPUProfileNode::create()
+ .setFunctionName(toProtocolString(node->GetFunctionName()))
+ .setScriptId(String16::number(node->GetScriptId()))
+ .setUrl(toProtocolString(node->GetScriptResourceName()))
+ .setLineNumber(node->GetLineNumber())
+ .setColumnNumber(node->GetColumnNumber())
+ .setHitCount(node->GetHitCount())
+ .setCallUID(node->GetCallUid())
+ .setChildren(std::move(children))
+ .setPositionTicks(std::move(positionTicks))
+ .setDeoptReason(node->GetBailoutReason())
+ .setId(node->GetNodeId()).build();
+ return result;
+}
+
+std::unique_ptr<protocol::Array<int>> buildInspectorObjectForSamples(v8::CpuProfile* v8profile)
+{
+ std::unique_ptr<protocol::Array<int>> array = protocol::Array<int>::create();
+ int count = v8profile->GetSamplesCount();
+ for (int i = 0; i < count; i++)
+ array->addItem(v8profile->GetSample(i)->GetNodeId());
+ return array;
+}
+
+std::unique_ptr<protocol::Array<double>> buildInspectorObjectForTimestamps(v8::CpuProfile* v8profile)
+{
+ std::unique_ptr<protocol::Array<double>> array = protocol::Array<double>::create();
+ int count = v8profile->GetSamplesCount();
+ for (int i = 0; i < count; i++)
+ array->addItem(v8profile->GetSampleTimestamp(i));
+ return array;
+}
+
+std::unique_ptr<protocol::Profiler::CPUProfile> createCPUProfile(v8::Isolate* isolate, v8::CpuProfile* v8profile)
+{
+ std::unique_ptr<protocol::Profiler::CPUProfile> profile = protocol::Profiler::CPUProfile::create()
+ .setHead(buildInspectorObjectFor(isolate, v8profile->GetTopDownRoot()))
+ .setStartTime(static_cast<double>(v8profile->GetStartTime()) / 1000000)
+ .setEndTime(static_cast<double>(v8profile->GetEndTime()) / 1000000).build();
+ profile->setSamples(buildInspectorObjectForSamples(v8profile));
+ profile->setTimestamps(buildInspectorObjectForTimestamps(v8profile));
+ return profile;
+}
+
+std::unique_ptr<protocol::Debugger::Location> currentDebugLocation(V8DebuggerImpl* debugger)
+{
+ std::unique_ptr<V8StackTrace> callStack = debugger->captureStackTrace(1);
+ std::unique_ptr<protocol::Debugger::Location> location = protocol::Debugger::Location::create()
+ .setScriptId(callStack->topScriptId())
+ .setLineNumber(callStack->topLineNumber()).build();
+ location->setColumnNumber(callStack->topColumnNumber());
+ return location;
+}
+
+volatile int s_lastProfileId = 0;
+
+} // namespace
+
+class V8ProfilerAgentImpl::ProfileDescriptor {
+public:
+ ProfileDescriptor(const String16& id, const String16& title)
+ : m_id(id)
+ , m_title(title) { }
+ String16 m_id;
+ String16 m_title;
+};
+
+V8ProfilerAgentImpl::V8ProfilerAgentImpl(V8InspectorSessionImpl* session)
+ : m_session(session)
+ , m_isolate(m_session->debugger()->isolate())
+ , m_state(nullptr)
+ , m_frontend(nullptr)
+ , m_enabled(false)
+ , m_recordingCPUProfile(false)
+{
+}
+
+V8ProfilerAgentImpl::~V8ProfilerAgentImpl()
+{
+}
+
+void V8ProfilerAgentImpl::consoleProfile(const String16& title)
+{
+ if (!m_enabled)
+ return;
+ DCHECK(m_frontend);
+ String16 id = nextProfileId();
+ m_startedProfiles.append(ProfileDescriptor(id, title));
+ startProfiling(id);
+ m_frontend->consoleProfileStarted(id, currentDebugLocation(m_session->debugger()), title);
+}
+
+void V8ProfilerAgentImpl::consoleProfileEnd(const String16& title)
+{
+ if (!m_enabled)
+ return;
+ DCHECK(m_frontend);
+ String16 id;
+ String16 resolvedTitle;
+ // Take last started profile if no title was passed.
+ if (title.isEmpty()) {
+ if (m_startedProfiles.isEmpty())
+ return;
+ id = m_startedProfiles.last().m_id;
+ resolvedTitle = m_startedProfiles.last().m_title;
+ m_startedProfiles.removeLast();
+ } else {
+ for (size_t i = 0; i < m_startedProfiles.size(); i++) {
+ if (m_startedProfiles[i].m_title == title) {
+ resolvedTitle = title;
+ id = m_startedProfiles[i].m_id;
+ m_startedProfiles.remove(i);
+ break;
+ }
+ }
+ if (id.isEmpty())
+ return;
+ }
+ std::unique_ptr<protocol::Profiler::CPUProfile> profile = stopProfiling(id, true);
+ if (!profile)
+ return;
+ std::unique_ptr<protocol::Debugger::Location> location = currentDebugLocation(m_session->debugger());
+ m_frontend->consoleProfileFinished(id, std::move(location), std::move(profile), resolvedTitle);
+}
+
+void V8ProfilerAgentImpl::enable(ErrorString*)
+{
+ if (m_enabled)
+ return;
+ m_enabled = true;
+ m_state->setBoolean(ProfilerAgentState::profilerEnabled, true);
+ m_session->changeInstrumentationCounter(+1);
+}
+
+void V8ProfilerAgentImpl::disable(ErrorString* errorString)
+{
+ if (!m_enabled)
+ return;
+ m_session->changeInstrumentationCounter(-1);
+ for (size_t i = m_startedProfiles.size(); i > 0; --i)
+ stopProfiling(m_startedProfiles[i - 1].m_id, false);
+ m_startedProfiles.clear();
+ stop(nullptr, nullptr);
+ m_enabled = false;
+ m_state->setBoolean(ProfilerAgentState::profilerEnabled, false);
+}
+
+void V8ProfilerAgentImpl::setSamplingInterval(ErrorString* error, int interval)
+{
+ if (m_recordingCPUProfile) {
+ *error = "Cannot change sampling interval when profiling.";
+ return;
+ }
+ m_state->setNumber(ProfilerAgentState::samplingInterval, interval);
+ m_isolate->GetCpuProfiler()->SetSamplingInterval(interval);
+}
+
+void V8ProfilerAgentImpl::clearFrontend()
+{
+ ErrorString error;
+ disable(&error);
+ DCHECK(m_frontend);
+ m_frontend = nullptr;
+}
+
+void V8ProfilerAgentImpl::restore()
+{
+ DCHECK(!m_enabled);
+ if (!m_state->booleanProperty(ProfilerAgentState::profilerEnabled, false))
+ return;
+ m_enabled = true;
+ m_session->changeInstrumentationCounter(+1);
+ int interval = 0;
+ m_state->getNumber(ProfilerAgentState::samplingInterval, &interval);
+ if (interval)
+ m_isolate->GetCpuProfiler()->SetSamplingInterval(interval);
+ if (m_state->booleanProperty(ProfilerAgentState::userInitiatedProfiling, false)) {
+ ErrorString error;
+ start(&error);
+ }
+}
+
+void V8ProfilerAgentImpl::start(ErrorString* error)
+{
+ if (m_recordingCPUProfile)
+ return;
+ if (!m_enabled) {
+ *error = "Profiler is not enabled";
+ return;
+ }
+ m_recordingCPUProfile = true;
+ m_frontendInitiatedProfileId = nextProfileId();
+ startProfiling(m_frontendInitiatedProfileId);
+ m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, true);
+ m_session->client()->profilingStarted();
+}
+
+void V8ProfilerAgentImpl::stop(ErrorString* errorString, std::unique_ptr<protocol::Profiler::CPUProfile>* profile)
+{
+ if (!m_recordingCPUProfile) {
+ if (errorString)
+ *errorString = "No recording profiles found";
+ return;
+ }
+ m_recordingCPUProfile = false;
+ std::unique_ptr<protocol::Profiler::CPUProfile> cpuProfile = stopProfiling(m_frontendInitiatedProfileId, !!profile);
+ if (profile) {
+ *profile = std::move(cpuProfile);
+ if (!profile->get() && errorString)
+ *errorString = "Profile is not found";
+ }
+ m_frontendInitiatedProfileId = String16();
+ m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, false);
+ m_session->client()->profilingStopped();
+}
+
+String16 V8ProfilerAgentImpl::nextProfileId()
+{
+ return String16::number(atomicIncrement(&s_lastProfileId));
+}
+
+void V8ProfilerAgentImpl::startProfiling(const String16& title)
+{
+ v8::HandleScope handleScope(m_isolate);
+ m_isolate->GetCpuProfiler()->StartProfiling(toV8String(m_isolate, title), true);
+}
+
+std::unique_ptr<protocol::Profiler::CPUProfile> V8ProfilerAgentImpl::stopProfiling(const String16& title, bool serialize)
+{
+ v8::HandleScope handleScope(m_isolate);
+ v8::CpuProfile* profile = m_isolate->GetCpuProfiler()->StopProfiling(toV8String(m_isolate, title));
+ if (!profile)
+ return nullptr;
+ std::unique_ptr<protocol::Profiler::CPUProfile> result;
+ if (serialize)
+ result = createCPUProfile(m_isolate, profile);
+ profile->Delete();
+ return result;
+}
+
+bool V8ProfilerAgentImpl::isRecording() const
+{
+ return m_recordingCPUProfile || !m_startedProfiles.isEmpty();
+}
+
+} // namespace blink
diff --git a/deps/v8_inspector/platform/v8_inspector/V8ProfilerAgentImpl.h b/deps/v8_inspector/platform/v8_inspector/V8ProfilerAgentImpl.h
new file mode 100644
index 0000000000..76bbfd4306
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8ProfilerAgentImpl.h
@@ -0,0 +1,65 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8ProfilerAgentImpl_h
+#define V8ProfilerAgentImpl_h
+
+#include "platform/inspector_protocol/Allocator.h"
+#include "platform/inspector_protocol/Frontend.h"
+#include "platform/inspector_protocol/String16.h"
+#include "platform/v8_inspector/public/V8ProfilerAgent.h"
+
+namespace v8 {
+class Isolate;
+}
+
+namespace blink {
+
+class V8InspectorSessionImpl;
+
+class V8ProfilerAgentImpl : public V8ProfilerAgent {
+ PROTOCOL_DISALLOW_COPY(V8ProfilerAgentImpl);
+public:
+ explicit V8ProfilerAgentImpl(V8InspectorSessionImpl*);
+ ~V8ProfilerAgentImpl() override;
+
+ bool enabled() const { return m_enabled; }
+
+ void setInspectorState(protocol::DictionaryValue* state) override { m_state = state; }
+ void setFrontend(protocol::Frontend::Profiler* frontend) override { m_frontend = frontend; }
+ void clearFrontend() override;
+ void restore() override;
+
+ void enable(ErrorString*) override;
+ void disable(ErrorString*) override;
+ void setSamplingInterval(ErrorString*, int) override;
+ void start(ErrorString*) override;
+ void stop(ErrorString*, std::unique_ptr<protocol::Profiler::CPUProfile>*) override;
+
+ void consoleProfile(const String16& title);
+ void consoleProfileEnd(const String16& title);
+
+private:
+ String16 nextProfileId();
+
+ void startProfiling(const String16& title);
+ std::unique_ptr<protocol::Profiler::CPUProfile> stopProfiling(const String16& title, bool serialize);
+
+ bool isRecording() const;
+
+ V8InspectorSessionImpl* m_session;
+ v8::Isolate* m_isolate;
+ protocol::DictionaryValue* m_state;
+ protocol::Frontend::Profiler* m_frontend;
+ bool m_enabled;
+ bool m_recordingCPUProfile;
+ class ProfileDescriptor;
+ protocol::Vector<ProfileDescriptor> m_startedProfiles;
+ String16 m_frontendInitiatedProfileId;
+};
+
+} // namespace blink
+
+
+#endif // !defined(V8ProfilerAgentImpl_h)
diff --git a/deps/v8_inspector/platform/v8_inspector/V8Regex.cpp b/deps/v8_inspector/platform/v8_inspector/V8Regex.cpp
new file mode 100644
index 0000000000..d29c916aa2
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8Regex.cpp
@@ -0,0 +1,93 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/v8_inspector/V8Regex.h"
+
+#include "platform/inspector_protocol/Collections.h"
+#include "platform/v8_inspector/V8Compat.h"
+#include "platform/v8_inspector/V8DebuggerImpl.h"
+#include "platform/v8_inspector/V8StringUtil.h"
+#include "platform/v8_inspector/public/V8DebuggerClient.h"
+
+#include <limits.h>
+
+namespace blink {
+
+V8Regex::V8Regex(V8DebuggerImpl* debugger, const String16& pattern, bool caseSensitive, bool multiline)
+ : m_debugger(debugger)
+{
+ v8::Isolate* isolate = m_debugger->isolate();
+ v8::HandleScope handleScope(isolate);
+ v8::Local<v8::Context> context = m_debugger->regexContext();
+ v8::Context::Scope contextScope(context);
+ v8::TryCatch tryCatch(isolate);
+
+ unsigned flags = v8::RegExp::kNone;
+ if (!caseSensitive)
+ flags |= v8::RegExp::kIgnoreCase;
+ if (multiline)
+ flags |= v8::RegExp::kMultiline;
+
+ v8::Local<v8::RegExp> regex;
+ if (v8::RegExp::New(context, toV8String(isolate, pattern), static_cast<v8::RegExp::Flags>(flags)).ToLocal(&regex))
+ m_regex.Reset(isolate, regex);
+ else if (tryCatch.HasCaught())
+ m_errorMessage = toProtocolString(tryCatch.Message()->Get());
+ else
+ m_errorMessage = "Internal error";
+}
+
+int V8Regex::match(const String16& string, int startFrom, int* matchLength) const
+{
+ if (matchLength)
+ *matchLength = 0;
+
+ if (m_regex.IsEmpty() || string.isEmpty())
+ return -1;
+
+ // v8 strings are limited to int.
+ if (string.length() > INT_MAX)
+ return -1;
+
+ v8::Isolate* isolate = m_debugger->isolate();
+ v8::HandleScope handleScope(isolate);
+ v8::Local<v8::Context> context = m_debugger->regexContext();
+ v8::MicrotasksScope microtasks(isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
+ v8::TryCatch tryCatch(isolate);
+
+ v8::Local<v8::RegExp> regex = m_regex.Get(isolate);
+ v8::Local<v8::Value> exec;
+ if (!regex->Get(context, toV8StringInternalized(isolate, "exec")).ToLocal(&exec))
+ return -1;
+ v8::Local<v8::Value> argv[] = { toV8String(isolate, string.substring(startFrom)) };
+ v8::Local<v8::Value> returnValue;
+ if (!exec.As<v8::Function>()->Call(context, regex, PROTOCOL_ARRAY_LENGTH(argv), argv).ToLocal(&returnValue))
+ return -1;
+
+ // RegExp#exec returns null if there's no match, otherwise it returns an
+ // Array of strings with the first being the whole match string and others
+ // being subgroups. The Array also has some random properties tacked on like
+ // "index" which is the offset of the match.
+ //
+ // https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/RegExp/exec
+
+ DCHECK(!returnValue.IsEmpty());
+ if (!returnValue->IsArray())
+ return -1;
+
+ v8::Local<v8::Array> result = returnValue.As<v8::Array>();
+ v8::Local<v8::Value> matchOffset;
+ if (!result->Get(context, toV8StringInternalized(isolate, "index")).ToLocal(&matchOffset))
+ return -1;
+ if (matchLength) {
+ v8::Local<v8::Value> match;
+ if (!result->Get(context, 0).ToLocal(&match))
+ return -1;
+ *matchLength = match.As<v8::String>()->Length();
+ }
+
+ return matchOffset.As<v8::Int32>()->Value() + startFrom;
+}
+
+} // namespace blink
diff --git a/deps/v8_inspector/platform/v8_inspector/V8Regex.h b/deps/v8_inspector/platform/v8_inspector/V8Regex.h
new file mode 100644
index 0000000000..983717d971
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8Regex.h
@@ -0,0 +1,37 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8Regex_h
+#define V8Regex_h
+
+#include "platform/inspector_protocol/Allocator.h"
+#include "platform/inspector_protocol/String16.h"
+#include <v8.h>
+
+namespace blink {
+
+class V8DebuggerImpl;
+
+enum MultilineMode {
+ MultilineDisabled,
+ MultilineEnabled
+};
+
+class V8Regex {
+ PROTOCOL_DISALLOW_COPY(V8Regex);
+public:
+ V8Regex(V8DebuggerImpl*, const String16&, bool caseSensitive, bool multiline = false);
+ int match(const String16&, int startFrom = 0, int* matchLength = 0) const;
+ bool isValid() const { return !m_regex.IsEmpty(); }
+ const String16& errorMessage() const { return m_errorMessage; }
+
+private:
+ V8DebuggerImpl* m_debugger;
+ v8::Global<v8::RegExp> m_regex;
+ String16 m_errorMessage;
+};
+
+} // namespace blink
+
+#endif // V8Regex_h
diff --git a/deps/v8_inspector/platform/v8_inspector/V8RuntimeAgentImpl.cpp b/deps/v8_inspector/platform/v8_inspector/V8RuntimeAgentImpl.cpp
new file mode 100644
index 0000000000..6a2611f87e
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8RuntimeAgentImpl.cpp
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "platform/v8_inspector/V8RuntimeAgentImpl.h"
+
+#include "platform/inspector_protocol/Values.h"
+#include "platform/v8_inspector/InjectedScript.h"
+#include "platform/v8_inspector/InspectedContext.h"
+#include "platform/v8_inspector/RemoteObjectId.h"
+#include "platform/v8_inspector/V8DebuggerImpl.h"
+#include "platform/v8_inspector/V8InspectorSessionImpl.h"
+#include "platform/v8_inspector/V8StringUtil.h"
+#include "platform/v8_inspector/public/V8DebuggerClient.h"
+
+namespace blink {
+
+namespace V8RuntimeAgentImplState {
+static const char customObjectFormatterEnabled[] = "customObjectFormatterEnabled";
+static const char runtimeEnabled[] = "runtimeEnabled";
+};
+
+using protocol::Runtime::ExceptionDetails;
+using protocol::Runtime::RemoteObject;
+
+static bool hasInternalError(ErrorString* errorString, bool hasError)
+{
+ if (hasError)
+ *errorString = "Internal error";
+ return hasError;
+}
+
+V8RuntimeAgentImpl::V8RuntimeAgentImpl(V8InspectorSessionImpl* session)
+ : m_session(session)
+ , m_state(nullptr)
+ , m_frontend(nullptr)
+ , m_debugger(session->debugger())
+ , m_enabled(false)
+{
+}
+
+V8RuntimeAgentImpl::~V8RuntimeAgentImpl()
+{
+}
+
+void V8RuntimeAgentImpl::evaluate(
+ ErrorString* errorString,
+ const String16& expression,
+ const Maybe<String16>& objectGroup,
+ const Maybe<bool>& includeCommandLineAPI,
+ const Maybe<bool>& doNotPauseOnExceptionsAndMuteConsole,
+ const Maybe<int>& executionContextId,
+ const Maybe<bool>& returnByValue,
+ const Maybe<bool>& generatePreview,
+ const Maybe<bool>& userGesture,
+ std::unique_ptr<RemoteObject>* result,
+ Maybe<bool>* wasThrown,
+ Maybe<ExceptionDetails>* exceptionDetails)
+{
+ int contextId;
+ if (executionContextId.isJust()) {
+ contextId = executionContextId.fromJust();
+ } else {
+ contextId = m_debugger->client()->ensureDefaultContextInGroup(m_session->contextGroupId());
+ if (!contextId) {
+ *errorString = "Cannot find default execution context";
+ return;
+ }
+ }
+
+ InjectedScript::ContextScope scope(errorString, m_debugger, m_session->contextGroupId(), contextId);
+ if (!scope.initialize())
+ return;
+
+ if (doNotPauseOnExceptionsAndMuteConsole.fromMaybe(false))
+ scope.ignoreExceptionsAndMuteConsole();
+ if (userGesture.fromMaybe(false))
+ scope.pretendUserGesture();
+
+ if (includeCommandLineAPI.fromMaybe(false) && !scope.installCommandLineAPI())
+ return;
+
+ bool evalIsDisabled = !scope.context()->IsCodeGenerationFromStringsAllowed();
+ // Temporarily enable allow evals for inspector.
+ if (evalIsDisabled)
+ scope.context()->AllowCodeGenerationFromStrings(true);
+
+ v8::MaybeLocal<v8::Value> maybeResultValue;
+ v8::Local<v8::Script> script = m_debugger->compileInternalScript(scope.context(), toV8String(m_debugger->isolate(), expression), String16());
+ if (!script.IsEmpty())
+ maybeResultValue = m_debugger->runCompiledScript(scope.context(), script);
+
+ if (evalIsDisabled)
+ scope.context()->AllowCodeGenerationFromStrings(false);
+
+ // Re-initialize after running client's code, as it could have destroyed context or session.
+ if (!scope.initialize())
+ return;
+ scope.injectedScript()->wrapEvaluateResult(errorString,
+ maybeResultValue,
+ scope.tryCatch(),
+ objectGroup.fromMaybe(""),
+ returnByValue.fromMaybe(false),
+ generatePreview.fromMaybe(false),
+ result,
+ wasThrown,
+ exceptionDetails);
+}
+
+void V8RuntimeAgentImpl::callFunctionOn(ErrorString* errorString,
+ const String16& objectId,
+ const String16& expression,
+ const Maybe<protocol::Array<protocol::Runtime::CallArgument>>& optionalArguments,
+ const Maybe<bool>& doNotPauseOnExceptionsAndMuteConsole,
+ const Maybe<bool>& returnByValue,
+ const Maybe<bool>& generatePreview,
+ const Maybe<bool>& userGesture,
+ std::unique_ptr<RemoteObject>* result,
+ Maybe<bool>* wasThrown)
+{
+ InjectedScript::ObjectScope scope(errorString, m_debugger, m_session->contextGroupId(), objectId);
+ if (!scope.initialize())
+ return;
+
+ std::unique_ptr<v8::Local<v8::Value>[]> argv = nullptr;
+ int argc = 0;
+ if (optionalArguments.isJust()) {
+ protocol::Array<protocol::Runtime::CallArgument>* arguments = optionalArguments.fromJust();
+ argc = arguments->length();
+ argv.reset(new v8::Local<v8::Value>[argc]);
+ for (int i = 0; i < argc; ++i) {
+ v8::Local<v8::Value> argumentValue;
+ if (!scope.injectedScript()->resolveCallArgument(errorString, arguments->get(i)).ToLocal(&argumentValue))
+ return;
+ argv[i] = argumentValue;
+ }
+ }
+
+ if (doNotPauseOnExceptionsAndMuteConsole.fromMaybe(false))
+ scope.ignoreExceptionsAndMuteConsole();
+ if (userGesture.fromMaybe(false))
+ scope.pretendUserGesture();
+
+ v8::MaybeLocal<v8::Value> maybeFunctionValue = m_debugger->compileAndRunInternalScript(scope.context(), toV8String(m_debugger->isolate(), "(" + expression + ")"));
+ // Re-initialize after running client's code, as it could have destroyed context or session.
+ if (!scope.initialize())
+ return;
+
+ if (scope.tryCatch().HasCaught()) {
+ scope.injectedScript()->wrapEvaluateResult(errorString, maybeFunctionValue, scope.tryCatch(), scope.objectGroupName(), false, false, result, wasThrown, nullptr);
+ return;
+ }
+
+ v8::Local<v8::Value> functionValue;
+ if (!maybeFunctionValue.ToLocal(&functionValue) || !functionValue->IsFunction()) {
+ *errorString = "Given expression does not evaluate to a function";
+ return;
+ }
+
+ v8::MaybeLocal<v8::Value> maybeResultValue = m_debugger->callFunction(functionValue.As<v8::Function>(), scope.context(), scope.object(), argc, argv.get());
+ // Re-initialize after running client's code, as it could have destroyed context or session.
+ if (!scope.initialize())
+ return;
+
+ scope.injectedScript()->wrapEvaluateResult(errorString, maybeResultValue, scope.tryCatch(), scope.objectGroupName(), returnByValue.fromMaybe(false), generatePreview.fromMaybe(false), result, wasThrown, nullptr);
+}
+
+void V8RuntimeAgentImpl::getProperties(
+ ErrorString* errorString,
+ const String16& objectId,
+ const Maybe<bool>& ownProperties,
+ const Maybe<bool>& accessorPropertiesOnly,
+ const Maybe<bool>& generatePreview,
+ std::unique_ptr<protocol::Array<protocol::Runtime::PropertyDescriptor>>* result,
+ Maybe<protocol::Array<protocol::Runtime::InternalPropertyDescriptor>>* internalProperties,
+ Maybe<ExceptionDetails>* exceptionDetails)
+{
+ using protocol::Runtime::InternalPropertyDescriptor;
+
+ InjectedScript::ObjectScope scope(errorString, m_debugger, m_session->contextGroupId(), objectId);
+ if (!scope.initialize())
+ return;
+
+ scope.ignoreExceptionsAndMuteConsole();
+ if (!scope.object()->IsObject()) {
+ *errorString = "Value with given id is not an object";
+ return;
+ }
+
+ v8::Local<v8::Object> object = scope.object().As<v8::Object>();
+ scope.injectedScript()->getProperties(errorString, object, scope.objectGroupName(), ownProperties.fromMaybe(false), accessorPropertiesOnly.fromMaybe(false), generatePreview.fromMaybe(false), result, exceptionDetails);
+ if (!errorString->isEmpty() || exceptionDetails->isJust() || accessorPropertiesOnly.fromMaybe(false))
+ return;
+ v8::Local<v8::Array> propertiesArray;
+ if (hasInternalError(errorString, !v8::Debug::GetInternalProperties(m_debugger->isolate(), scope.object()).ToLocal(&propertiesArray)))
+ return;
+ std::unique_ptr<protocol::Array<InternalPropertyDescriptor>> propertiesProtocolArray = protocol::Array<InternalPropertyDescriptor>::create();
+ for (uint32_t i = 0; i < propertiesArray->Length(); i += 2) {
+ v8::Local<v8::Value> name;
+ if (hasInternalError(errorString, !propertiesArray->Get(scope.context(), i).ToLocal(&name)) || !name->IsString())
+ return;
+ v8::Local<v8::Value> value;
+ if (hasInternalError(errorString, !propertiesArray->Get(scope.context(), i + 1).ToLocal(&value)))
+ return;
+ std::unique_ptr<RemoteObject> wrappedValue = scope.injectedScript()->wrapObject(errorString, value, scope.objectGroupName());
+ if (!wrappedValue)
+ return;
+ propertiesProtocolArray->addItem(InternalPropertyDescriptor::create()
+ .setName(toProtocolString(name.As<v8::String>()))
+ .setValue(std::move(wrappedValue)).build());
+ }
+ if (!propertiesProtocolArray->length())
+ return;
+ *internalProperties = std::move(propertiesProtocolArray);
+}
+
+void V8RuntimeAgentImpl::releaseObject(ErrorString* errorString, const String16& objectId)
+{
+ InjectedScript::ObjectScope scope(errorString, m_debugger, m_session->contextGroupId(), objectId);
+ if (!scope.initialize())
+ return;
+ scope.injectedScript()->releaseObject(objectId);
+}
+
+void V8RuntimeAgentImpl::releaseObjectGroup(ErrorString*, const String16& objectGroup)
+{
+ m_session->releaseObjectGroup(objectGroup);
+}
+
+void V8RuntimeAgentImpl::run(ErrorString* errorString)
+{
+ m_session->client()->resumeStartup();
+}
+
+void V8RuntimeAgentImpl::setCustomObjectFormatterEnabled(ErrorString*, bool enabled)
+{
+ m_state->setBoolean(V8RuntimeAgentImplState::customObjectFormatterEnabled, enabled);
+ m_session->setCustomObjectFormatterEnabled(enabled);
+}
+
+void V8RuntimeAgentImpl::compileScript(ErrorString* errorString,
+ const String16& expression,
+ const String16& sourceURL,
+ bool persistScript,
+ int executionContextId,
+ Maybe<String16>* scriptId,
+ Maybe<ExceptionDetails>* exceptionDetails)
+{
+ if (!m_enabled) {
+ *errorString = "Runtime agent is not enabled";
+ return;
+ }
+ InjectedScript::ContextScope scope(errorString, m_debugger, m_session->contextGroupId(), executionContextId);
+ if (!scope.initialize())
+ return;
+
+ v8::Local<v8::Script> script = m_debugger->compileInternalScript(scope.context(), toV8String(m_debugger->isolate(), expression), sourceURL);
+ if (script.IsEmpty()) {
+ v8::Local<v8::Message> message = scope.tryCatch().Message();
+ if (!message.IsEmpty())
+ *exceptionDetails = scope.injectedScript()->createExceptionDetails(message);
+ else
+ *errorString = "Script compilation failed";
+ return;
+ }
+
+ if (!persistScript)
+ return;
+
+ String16 scriptValueId = String16::number(script->GetUnboundScript()->GetId());
+ std::unique_ptr<v8::Global<v8::Script>> global(new v8::Global<v8::Script>(m_debugger->isolate(), script));
+ m_compiledScripts.set(scriptValueId, std::move(global));
+ *scriptId = scriptValueId;
+}
+
+void V8RuntimeAgentImpl::runScript(ErrorString* errorString,
+ const String16& scriptId,
+ int executionContextId,
+ const Maybe<String16>& objectGroup,
+ const Maybe<bool>& doNotPauseOnExceptionsAndMuteConsole,
+ const Maybe<bool>& includeCommandLineAPI,
+ std::unique_ptr<RemoteObject>* result,
+ Maybe<ExceptionDetails>* exceptionDetails)
+{
+ if (!m_enabled) {
+ *errorString = "Runtime agent is not enabled";
+ return;
+ }
+
+ if (!m_compiledScripts.contains(scriptId)) {
+ *errorString = "Script execution failed";
+ return;
+ }
+
+ InjectedScript::ContextScope scope(errorString, m_debugger, m_session->contextGroupId(), executionContextId);
+ if (!scope.initialize())
+ return;
+
+ if (doNotPauseOnExceptionsAndMuteConsole.fromMaybe(false))
+ scope.ignoreExceptionsAndMuteConsole();
+
+ std::unique_ptr<v8::Global<v8::Script>> scriptWrapper = m_compiledScripts.take(scriptId);
+ v8::Local<v8::Script> script = scriptWrapper->Get(m_debugger->isolate());
+ if (script.IsEmpty()) {
+ *errorString = "Script execution failed";
+ return;
+ }
+
+ if (includeCommandLineAPI.fromMaybe(false) && !scope.installCommandLineAPI())
+ return;
+
+ v8::MaybeLocal<v8::Value> maybeResultValue = m_debugger->runCompiledScript(scope.context(), script);
+
+ // Re-initialize after running client's code, as it could have destroyed context or session.
+ if (!scope.initialize())
+ return;
+ scope.injectedScript()->wrapEvaluateResult(errorString, maybeResultValue, scope.tryCatch(), objectGroup.fromMaybe(""), false, false, result, nullptr, exceptionDetails);
+}
+
+void V8RuntimeAgentImpl::setInspectorState(protocol::DictionaryValue* state)
+{
+ m_state = state;
+}
+
+void V8RuntimeAgentImpl::setFrontend(protocol::Frontend::Runtime* frontend)
+{
+ m_frontend = frontend;
+}
+
+void V8RuntimeAgentImpl::clearFrontend()
+{
+ ErrorString error;
+ disable(&error);
+ DCHECK(m_frontend);
+ m_frontend = nullptr;
+}
+
+void V8RuntimeAgentImpl::restore()
+{
+ if (!m_state->booleanProperty(V8RuntimeAgentImplState::runtimeEnabled, false))
+ return;
+ m_frontend->executionContextsCleared();
+ ErrorString error;
+ enable(&error);
+ if (m_state->booleanProperty(V8RuntimeAgentImplState::customObjectFormatterEnabled, false))
+ m_session->setCustomObjectFormatterEnabled(true);
+}
+
+void V8RuntimeAgentImpl::enable(ErrorString* errorString)
+{
+ if (m_enabled)
+ return;
+ m_session->changeInstrumentationCounter(+1);
+ m_enabled = true;
+ m_state->setBoolean(V8RuntimeAgentImplState::runtimeEnabled, true);
+ v8::HandleScope handles(m_debugger->isolate());
+ m_session->reportAllContexts(this);
+}
+
+void V8RuntimeAgentImpl::disable(ErrorString* errorString)
+{
+ if (!m_enabled)
+ return;
+ m_enabled = false;
+ m_state->setBoolean(V8RuntimeAgentImplState::runtimeEnabled, false);
+ m_session->discardInjectedScripts();
+ reset();
+ m_session->changeInstrumentationCounter(-1);
+}
+
+void V8RuntimeAgentImpl::reset()
+{
+ m_compiledScripts.clear();
+ if (m_enabled) {
+ if (const V8DebuggerImpl::ContextByIdMap* contexts = m_debugger->contextGroup(m_session->contextGroupId())) {
+ for (auto& idContext : *contexts)
+ idContext.second->setReported(false);
+ }
+ m_frontend->executionContextsCleared();
+ }
+}
+
+void V8RuntimeAgentImpl::reportExecutionContextCreated(InspectedContext* context)
+{
+ if (!m_enabled)
+ return;
+ context->setReported(true);
+ std::unique_ptr<protocol::Runtime::ExecutionContextDescription> description = protocol::Runtime::ExecutionContextDescription::create()
+ .setId(context->contextId())
+ .setIsDefault(context->isDefault())
+ .setName(context->humanReadableName())
+ .setOrigin(context->origin())
+ .setFrameId(context->frameId()).build();
+ m_frontend->executionContextCreated(std::move(description));
+}
+
+void V8RuntimeAgentImpl::reportExecutionContextDestroyed(InspectedContext* context)
+{
+ if (m_enabled && context->isReported()) {
+ context->setReported(false);
+ m_frontend->executionContextDestroyed(context->contextId());
+ }
+}
+
+void V8RuntimeAgentImpl::inspect(std::unique_ptr<protocol::Runtime::RemoteObject> objectToInspect, std::unique_ptr<protocol::DictionaryValue> hints)
+{
+ if (m_enabled)
+ m_frontend->inspectRequested(std::move(objectToInspect), std::move(hints));
+}
+
+} // namespace blink
diff --git a/deps/v8_inspector/platform/v8_inspector/V8RuntimeAgentImpl.h b/deps/v8_inspector/platform/v8_inspector/V8RuntimeAgentImpl.h
new file mode 100644
index 0000000000..3870106acb
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8RuntimeAgentImpl.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef V8RuntimeAgentImpl_h
+#define V8RuntimeAgentImpl_h
+
+#include "platform/inspector_protocol/Allocator.h"
+#include "platform/inspector_protocol/Frontend.h"
+#include "platform/v8_inspector/public/V8RuntimeAgent.h"
+
+namespace blink {
+
+class InjectedScript;
+class InspectedContext;
+class RemoteObjectIdBase;
+class V8DebuggerImpl;
+class V8InspectorSessionImpl;
+
+namespace protocol {
+class DictionaryValue;
+}
+
+using protocol::Maybe;
+
+class V8RuntimeAgentImpl : public V8RuntimeAgent {
+ PROTOCOL_DISALLOW_COPY(V8RuntimeAgentImpl);
+public:
+ explicit V8RuntimeAgentImpl(V8InspectorSessionImpl*);
+ ~V8RuntimeAgentImpl() override;
+
+ // State management methods.
+ void setInspectorState(protocol::DictionaryValue*) override;
+ void setFrontend(protocol::Frontend::Runtime*) override;
+ void clearFrontend() override;
+ void restore() override;
+
+ // Part of the protocol.
+ void enable(ErrorString*) override;
+ void disable(ErrorString*) override;
+ void evaluate(ErrorString*,
+ const String16& expression,
+ const Maybe<String16>& objectGroup,
+ const Maybe<bool>& includeCommandLineAPI,
+ const Maybe<bool>& doNotPauseOnExceptionsAndMuteConsole,
+ const Maybe<int>& executionContextId,
+ const Maybe<bool>& returnByValue,
+ const Maybe<bool>& generatePreview,
+ const Maybe<bool>& userGesture,
+ std::unique_ptr<protocol::Runtime::RemoteObject>* result,
+ Maybe<bool>* wasThrown,
+ Maybe<protocol::Runtime::ExceptionDetails>*) override;
+ void callFunctionOn(ErrorString*,
+ const String16& objectId,
+ const String16& expression,
+ const Maybe<protocol::Array<protocol::Runtime::CallArgument>>& optionalArguments,
+ const Maybe<bool>& doNotPauseOnExceptionsAndMuteConsole,
+ const Maybe<bool>& returnByValue,
+ const Maybe<bool>& generatePreview,
+ const Maybe<bool>& userGesture,
+ std::unique_ptr<protocol::Runtime::RemoteObject>* result,
+ Maybe<bool>* wasThrown) override;
+ void releaseObject(ErrorString*, const String16& objectId) override;
+ void getProperties(ErrorString*,
+ const String16& objectId,
+ const Maybe<bool>& ownProperties,
+ const Maybe<bool>& accessorPropertiesOnly,
+ const Maybe<bool>& generatePreview,
+ std::unique_ptr<protocol::Array<protocol::Runtime::PropertyDescriptor>>* result,
+ Maybe<protocol::Array<protocol::Runtime::InternalPropertyDescriptor>>* internalProperties,
+ Maybe<protocol::Runtime::ExceptionDetails>*) override;
+ void releaseObjectGroup(ErrorString*, const String16& objectGroup) override;
+ void run(ErrorString*) override;
+ void setCustomObjectFormatterEnabled(ErrorString*, bool) override;
+ void compileScript(ErrorString*,
+ const String16& expression,
+ const String16& sourceURL,
+ bool persistScript,
+ int executionContextId,
+ Maybe<String16>*,
+ Maybe<protocol::Runtime::ExceptionDetails>*) override;
+ void runScript(ErrorString*,
+ const String16&,
+ int executionContextId,
+ const Maybe<String16>& objectGroup,
+ const Maybe<bool>& doNotPauseOnExceptionsAndMuteConsole,
+ const Maybe<bool>& includeCommandLineAPI,
+ std::unique_ptr<protocol::Runtime::RemoteObject>* result,
+ Maybe<protocol::Runtime::ExceptionDetails>*) override;
+
+ void reset();
+ void reportExecutionContextCreated(InspectedContext*);
+ void reportExecutionContextDestroyed(InspectedContext*);
+ void inspect(std::unique_ptr<protocol::Runtime::RemoteObject> objectToInspect, std::unique_ptr<protocol::DictionaryValue> hints);
+
+private:
+ V8InspectorSessionImpl* m_session;
+ protocol::DictionaryValue* m_state;
+ protocol::Frontend::Runtime* m_frontend;
+ V8DebuggerImpl* m_debugger;
+ bool m_enabled;
+ protocol::HashMap<String16, std::unique_ptr<v8::Global<v8::Script>>> m_compiledScripts;
+};
+
+} // namespace blink
+
+#endif // V8RuntimeAgentImpl_h
diff --git a/deps/v8_inspector/platform/v8_inspector/V8StackTraceImpl.cpp b/deps/v8_inspector/platform/v8_inspector/V8StackTraceImpl.cpp
new file mode 100644
index 0000000000..3cba145eaf
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8StackTraceImpl.cpp
@@ -0,0 +1,227 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/v8_inspector/V8StackTraceImpl.h"
+
+#include "platform/inspector_protocol/String16.h"
+#include "platform/v8_inspector/V8DebuggerAgentImpl.h"
+#include "platform/v8_inspector/V8DebuggerImpl.h"
+#include "platform/v8_inspector/V8StringUtil.h"
+#include "wtf/PtrUtil.h"
+
+#include <v8-debug.h>
+#include <v8-profiler.h>
+#include <v8-version.h>
+
+namespace blink {
+
+namespace {
+
+V8StackTraceImpl::Frame toFrame(v8::Local<v8::StackFrame> frame)
+{
+ String16 scriptId = String16::number(frame->GetScriptId());
+ String16 sourceName;
+ v8::Local<v8::String> sourceNameValue(frame->GetScriptNameOrSourceURL());
+ if (!sourceNameValue.IsEmpty())
+ sourceName = toProtocolString(sourceNameValue);
+
+ String16 functionName;
+ v8::Local<v8::String> functionNameValue(frame->GetFunctionName());
+ if (!functionNameValue.IsEmpty())
+ functionName = toProtocolString(functionNameValue);
+
+ int sourceLineNumber = frame->GetLineNumber();
+ int sourceColumn = frame->GetColumn();
+ return V8StackTraceImpl::Frame(functionName, scriptId, sourceName, sourceLineNumber, sourceColumn);
+}
+
+void toFramesVector(v8::Local<v8::StackTrace> stackTrace, protocol::Vector<V8StackTraceImpl::Frame>& frames, size_t maxStackSize, v8::Isolate* isolate)
+{
+ DCHECK(isolate->InContext());
+ int frameCount = stackTrace->GetFrameCount();
+ if (frameCount > static_cast<int>(maxStackSize))
+ frameCount = maxStackSize;
+ for (int i = 0; i < frameCount; i++) {
+ v8::Local<v8::StackFrame> stackFrame = stackTrace->GetFrame(i);
+ frames.append(toFrame(stackFrame));
+ }
+}
+
+} // namespace
+
+V8StackTraceImpl::Frame::Frame()
+ : m_functionName("undefined")
+ , m_scriptId("")
+ , m_scriptName("undefined")
+ , m_lineNumber(0)
+ , m_columnNumber(0)
+{
+}
+
+V8StackTraceImpl::Frame::Frame(const String16& functionName, const String16& scriptId, const String16& scriptName, int lineNumber, int column)
+ : m_functionName(functionName)
+ , m_scriptId(scriptId)
+ , m_scriptName(scriptName)
+ , m_lineNumber(lineNumber)
+ , m_columnNumber(column)
+{
+}
+
+V8StackTraceImpl::Frame::~Frame()
+{
+}
+
+// buildInspectorObject() and ScriptCallStack's toTracedValue() should set the same fields.
+// If either of them is modified, the other should be also modified.
+std::unique_ptr<protocol::Runtime::CallFrame> V8StackTraceImpl::Frame::buildInspectorObject() const
+{
+ return protocol::Runtime::CallFrame::create()
+ .setFunctionName(m_functionName)
+ .setScriptId(m_scriptId)
+ .setUrl(m_scriptName)
+ .setLineNumber(m_lineNumber)
+ .setColumnNumber(m_columnNumber)
+ .build();
+}
+
+std::unique_ptr<V8StackTraceImpl> V8StackTraceImpl::create(V8DebuggerAgentImpl* agent, v8::Local<v8::StackTrace> stackTrace, size_t maxStackSize, const String16& description)
+{
+ v8::Isolate* isolate = v8::Isolate::GetCurrent();
+ v8::HandleScope scope(isolate);
+ protocol::Vector<V8StackTraceImpl::Frame> frames;
+ if (!stackTrace.IsEmpty())
+ toFramesVector(stackTrace, frames, maxStackSize, isolate);
+
+ int maxAsyncCallChainDepth = 1;
+ V8StackTraceImpl* asyncCallChain = nullptr;
+ if (agent && maxStackSize > 1) {
+ asyncCallChain = agent->currentAsyncCallChain();
+ maxAsyncCallChainDepth = agent->maxAsyncCallChainDepth();
+ }
+
+ // Only the top stack in the chain may be empty, so ensure that second stack is non-empty (it's the top of appended chain).
+ if (asyncCallChain && asyncCallChain->isEmpty())
+ asyncCallChain = asyncCallChain->m_parent.get();
+
+ if (stackTrace.IsEmpty() && !asyncCallChain)
+ return nullptr;
+
+ std::unique_ptr<V8StackTraceImpl> result(new V8StackTraceImpl(description, frames, asyncCallChain ? asyncCallChain->clone() : nullptr));
+
+ // Crop to not exceed maxAsyncCallChainDepth.
+ V8StackTraceImpl* deepest = result.get();
+ while (deepest && maxAsyncCallChainDepth) {
+ deepest = deepest->m_parent.get();
+ maxAsyncCallChainDepth--;
+ }
+ if (deepest)
+ deepest->m_parent.reset();
+
+ return result;
+}
+
+std::unique_ptr<V8StackTraceImpl> V8StackTraceImpl::capture(V8DebuggerAgentImpl* agent, size_t maxStackSize, const String16& description)
+{
+ v8::Isolate* isolate = v8::Isolate::GetCurrent();
+ v8::HandleScope handleScope(isolate);
+ v8::Local<v8::StackTrace> stackTrace;
+ if (isolate->InContext()) {
+#if V8_MAJOR_VERSION >= 5
+ isolate->GetCpuProfiler()->CollectSample();
+#endif
+ stackTrace = v8::StackTrace::CurrentStackTrace(isolate, maxStackSize, stackTraceOptions);
+ }
+ return V8StackTraceImpl::create(agent, stackTrace, maxStackSize, description);
+}
+
+std::unique_ptr<V8StackTraceImpl> V8StackTraceImpl::clone()
+{
+ protocol::Vector<Frame> framesCopy(m_frames);
+ return wrapUnique(new V8StackTraceImpl(m_description, framesCopy, m_parent ? m_parent->clone() : nullptr));
+}
+
+V8StackTraceImpl::V8StackTraceImpl(const String16& description, protocol::Vector<Frame>& frames, std::unique_ptr<V8StackTraceImpl> parent)
+ : m_description(description)
+ , m_parent(std::move(parent))
+{
+ m_frames.swap(frames);
+}
+
+V8StackTraceImpl::~V8StackTraceImpl()
+{
+}
+
+String16 V8StackTraceImpl::topSourceURL() const
+{
+ DCHECK(m_frames.size());
+ return m_frames[0].m_scriptName;
+}
+
+int V8StackTraceImpl::topLineNumber() const
+{
+ DCHECK(m_frames.size());
+ return m_frames[0].m_lineNumber;
+}
+
+int V8StackTraceImpl::topColumnNumber() const
+{
+ DCHECK(m_frames.size());
+ return m_frames[0].m_columnNumber;
+}
+
+String16 V8StackTraceImpl::topFunctionName() const
+{
+ DCHECK(m_frames.size());
+ return m_frames[0].m_functionName;
+}
+
+String16 V8StackTraceImpl::topScriptId() const
+{
+ DCHECK(m_frames.size());
+ return m_frames[0].m_scriptId;
+}
+
+std::unique_ptr<protocol::Runtime::StackTrace> V8StackTraceImpl::buildInspectorObject() const
+{
+ std::unique_ptr<protocol::Array<protocol::Runtime::CallFrame>> frames = protocol::Array<protocol::Runtime::CallFrame>::create();
+ for (size_t i = 0; i < m_frames.size(); i++)
+ frames->addItem(m_frames.at(i).buildInspectorObject());
+
+ std::unique_ptr<protocol::Runtime::StackTrace> stackTrace = protocol::Runtime::StackTrace::create()
+ .setCallFrames(std::move(frames)).build();
+ if (!m_description.isEmpty())
+ stackTrace->setDescription(m_description);
+ if (m_parent)
+ stackTrace->setParent(m_parent->buildInspectorObject());
+ return stackTrace;
+}
+
+std::unique_ptr<protocol::Runtime::StackTrace> V8StackTraceImpl::buildInspectorObjectForTail(V8DebuggerAgentImpl* agent) const
+{
+ v8::HandleScope handleScope(v8::Isolate::GetCurrent());
+ // Next call collapses possible empty stack and ensures maxAsyncCallChainDepth.
+ std::unique_ptr<V8StackTraceImpl> fullChain = V8StackTraceImpl::create(agent, v8::Local<v8::StackTrace>(), V8StackTrace::maxCallStackSizeToCapture);
+ if (!fullChain || !fullChain->m_parent)
+ return nullptr;
+ return fullChain->m_parent->buildInspectorObject();
+}
+
+String16 V8StackTraceImpl::toString() const
+{
+ String16Builder stackTrace;
+ for (size_t i = 0; i < m_frames.size(); ++i) {
+ const Frame& frame = m_frames[i];
+ stackTrace.append("\n at " + (frame.functionName().length() ? frame.functionName() : "(anonymous function)"));
+ stackTrace.append(" (");
+ stackTrace.append(frame.sourceURL());
+ stackTrace.append(':');
+ stackTrace.appendNumber(frame.lineNumber());
+ stackTrace.append(':');
+ stackTrace.appendNumber(frame.columnNumber());
+ stackTrace.append(')');
+ }
+ return stackTrace.toString();
+}
+
+} // namespace blink
diff --git a/deps/v8_inspector/platform/v8_inspector/V8StackTraceImpl.h b/deps/v8_inspector/platform/v8_inspector/V8StackTraceImpl.h
new file mode 100644
index 0000000000..9b9bd1920a
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8StackTraceImpl.h
@@ -0,0 +1,74 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8StackTraceImpl_h
+#define V8StackTraceImpl_h
+
+#include "platform/inspector_protocol/Collections.h"
+#include "platform/v8_inspector/public/V8StackTrace.h"
+#include "wtf/PtrUtil.h"
+
+namespace blink {
+
+class TracedValue;
+class V8DebuggerAgentImpl;
+
+// Note: async stack trace may have empty top stack with non-empty tail to indicate
+// that current native-only state had some async story.
+// On the other hand, any non-top async stack is guaranteed to be non-empty.
+class V8StackTraceImpl final : public V8StackTrace {
+ PROTOCOL_DISALLOW_COPY(V8StackTraceImpl);
+public:
+ class Frame {
+ public:
+ Frame();
+ Frame(const String16& functionName, const String16& scriptId, const String16& scriptName, int lineNumber, int column = 0);
+ ~Frame();
+
+ const String16& functionName() const { return m_functionName; }
+ const String16& scriptId() const { return m_scriptId; }
+ const String16& sourceURL() const { return m_scriptName; }
+ int lineNumber() const { return m_lineNumber; }
+ int columnNumber() const { return m_columnNumber; }
+
+ private:
+ friend class V8StackTraceImpl;
+ std::unique_ptr<protocol::Runtime::CallFrame> buildInspectorObject() const;
+ void toTracedValue(TracedValue*) const;
+
+ String16 m_functionName;
+ String16 m_scriptId;
+ String16 m_scriptName;
+ int m_lineNumber;
+ int m_columnNumber;
+ };
+
+ static std::unique_ptr<V8StackTraceImpl> create(V8DebuggerAgentImpl*, v8::Local<v8::StackTrace>, size_t maxStackSize, const String16& description = String16());
+ static std::unique_ptr<V8StackTraceImpl> capture(V8DebuggerAgentImpl*, size_t maxStackSize, const String16& description = String16());
+
+ std::unique_ptr<V8StackTraceImpl> clone();
+ std::unique_ptr<protocol::Runtime::StackTrace> buildInspectorObjectForTail(V8DebuggerAgentImpl*) const;
+ ~V8StackTraceImpl() override;
+
+ // V8StackTrace implementation.
+ bool isEmpty() const override { return !m_frames.size(); };
+ String16 topSourceURL() const override;
+ int topLineNumber() const override;
+ int topColumnNumber() const override;
+ String16 topScriptId() const override;
+ String16 topFunctionName() const override;
+ std::unique_ptr<protocol::Runtime::StackTrace> buildInspectorObject() const override;
+ String16 toString() const override;
+
+private:
+ V8StackTraceImpl(const String16& description, protocol::Vector<Frame>& frames, std::unique_ptr<V8StackTraceImpl> parent);
+
+ String16 m_description;
+ protocol::Vector<Frame> m_frames;
+ std::unique_ptr<V8StackTraceImpl> m_parent;
+};
+
+} // namespace blink
+
+#endif // V8StackTraceImpl_h
diff --git a/deps/v8_inspector/platform/v8_inspector/V8StringUtil.cpp b/deps/v8_inspector/platform/v8_inspector/V8StringUtil.cpp
new file mode 100644
index 0000000000..e47981e72c
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8StringUtil.cpp
@@ -0,0 +1,280 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/v8_inspector/V8StringUtil.h"
+
+#include "platform/inspector_protocol/String16.h"
+#include "platform/v8_inspector/V8DebuggerImpl.h"
+#include "platform/v8_inspector/V8InspectorSessionImpl.h"
+#include "platform/v8_inspector/V8Regex.h"
+#include "platform/v8_inspector/public/V8ContentSearchUtil.h"
+#include "platform/v8_inspector/public/V8ToProtocolValue.h"
+
+namespace blink {
+
+namespace {
+
+String16 findMagicComment(const String16& content, const String16& name, bool multiline, bool* deprecated)
+{
+ DCHECK(name.find("=") == kNotFound);
+ if (deprecated)
+ *deprecated = false;
+
+ unsigned length = content.length();
+ unsigned nameLength = name.length();
+
+ size_t pos = length;
+ size_t equalSignPos = 0;
+ size_t closingCommentPos = 0;
+ while (true) {
+ pos = content.reverseFind(name, pos);
+ if (pos == kNotFound)
+ return String16();
+
+ // Check for a /\/[\/*][@#][ \t]/ regexp (length of 4) before found name.
+ if (pos < 4)
+ return String16();
+ pos -= 4;
+ if (content[pos] != '/')
+ continue;
+ if ((content[pos + 1] != '/' || multiline)
+ && (content[pos + 1] != '*' || !multiline))
+ continue;
+ if (content[pos + 2] != '#' && content[pos + 2] != '@')
+ continue;
+ if (content[pos + 3] != ' ' && content[pos + 3] != '\t')
+ continue;
+ equalSignPos = pos + 4 + nameLength;
+ if (equalSignPos < length && content[equalSignPos] != '=')
+ continue;
+ if (multiline) {
+ closingCommentPos = content.find("*/", equalSignPos + 1);
+ if (closingCommentPos == kNotFound)
+ return String16();
+ }
+
+ break;
+ }
+
+ if (deprecated && content[pos + 2] == '@')
+ *deprecated = true;
+
+ DCHECK(equalSignPos);
+ DCHECK(!multiline || closingCommentPos);
+ size_t urlPos = equalSignPos + 1;
+ String16 match = multiline
+ ? content.substring(urlPos, closingCommentPos - urlPos)
+ : content.substring(urlPos);
+
+ size_t newLine = match.find("\n");
+ if (newLine != kNotFound)
+ match = match.substring(0, newLine);
+ match = match.stripWhiteSpace();
+
+ String16 disallowedChars("\"' \t");
+ for (unsigned i = 0; i < match.length(); ++i) {
+ if (disallowedChars.find(match[i]) != kNotFound)
+ return "";
+ }
+
+ return match;
+}
+
+String16 createSearchRegexSource(const String16& text)
+{
+ String16Builder result;
+ String16 specials("[](){}+-*.,?\\^$|");
+
+ for (unsigned i = 0; i < text.length(); i++) {
+ if (specials.find(text[i]) != kNotFound)
+ result.append('\\');
+ result.append(text[i]);
+ }
+
+ return result.toString();
+}
+
+std::unique_ptr<protocol::Vector<unsigned>> lineEndings(const String16& text)
+{
+ std::unique_ptr<protocol::Vector<unsigned>> result(new protocol::Vector<unsigned>());
+
+ unsigned start = 0;
+ while (start < text.length()) {
+ size_t lineEnd = text.find('\n', start);
+ if (lineEnd == kNotFound)
+ break;
+
+ result->append(static_cast<unsigned>(lineEnd));
+ start = lineEnd + 1;
+ }
+ result->append(text.length());
+
+ return result;
+}
+
+protocol::Vector<std::pair<int, String16>> scriptRegexpMatchesByLines(const V8Regex& regex, const String16& text)
+{
+ protocol::Vector<std::pair<int, String16>> result;
+ if (text.isEmpty())
+ return result;
+
+ std::unique_ptr<protocol::Vector<unsigned>> endings(lineEndings(text));
+ unsigned size = endings->size();
+ unsigned start = 0;
+ for (unsigned lineNumber = 0; lineNumber < size; ++lineNumber) {
+ unsigned lineEnd = endings->at(lineNumber);
+ String16 line = text.substring(start, lineEnd - start);
+ if (line.endsWith('\r'))
+ line = line.substring(0, line.length() - 1);
+
+ int matchLength;
+ if (regex.match(line, 0, &matchLength) != -1)
+ result.append(std::pair<int, String16>(lineNumber, line));
+
+ start = lineEnd + 1;
+ }
+ return result;
+}
+
+std::unique_ptr<protocol::Debugger::SearchMatch> buildObjectForSearchMatch(int lineNumber, const String16& lineContent)
+{
+ return protocol::Debugger::SearchMatch::create()
+ .setLineNumber(lineNumber)
+ .setLineContent(lineContent)
+ .build();
+}
+
+std::unique_ptr<V8Regex> createSearchRegex(V8DebuggerImpl* debugger, const String16& query, bool caseSensitive, bool isRegex)
+{
+ String16 regexSource = isRegex ? query : createSearchRegexSource(query);
+ return wrapUnique(new V8Regex(debugger, regexSource, caseSensitive));
+}
+
+} // namespace
+
+v8::Local<v8::String> toV8String(v8::Isolate* isolate, const String16& string)
+{
+ if (string.isEmpty())
+ return v8::String::Empty(isolate);
+ return v8::String::NewFromTwoByte(isolate, reinterpret_cast<const uint16_t*>(string.characters16()), v8::NewStringType::kNormal, string.length()).ToLocalChecked();
+}
+
+v8::Local<v8::String> toV8StringInternalized(v8::Isolate* isolate, const String16& string)
+{
+ if (string.isEmpty())
+ return v8::String::Empty(isolate);
+ return v8::String::NewFromTwoByte(isolate, reinterpret_cast<const uint16_t*>(string.characters16()), v8::NewStringType::kInternalized, string.length()).ToLocalChecked();
+}
+
+String16 toProtocolString(v8::Local<v8::String> value)
+{
+ if (value.IsEmpty() || value->IsNull() || value->IsUndefined())
+ return String16();
+ std::unique_ptr<UChar[]> buffer(new UChar[value->Length()]);
+ value->Write(reinterpret_cast<uint16_t*>(buffer.get()), 0, value->Length());
+ return String16(buffer.get(), value->Length());
+}
+
+String16 toProtocolStringWithTypeCheck(v8::Local<v8::Value> value)
+{
+ if (value.IsEmpty() || !value->IsString())
+ return String16();
+ return toProtocolString(value.As<v8::String>());
+}
+
+namespace V8ContentSearchUtil {
+
+String16 findSourceURL(const String16& content, bool multiline, bool* deprecated)
+{
+ return findMagicComment(content, "sourceURL", multiline, deprecated);
+}
+
+String16 findSourceMapURL(const String16& content, bool multiline, bool* deprecated)
+{
+ return findMagicComment(content, "sourceMappingURL", multiline, deprecated);
+}
+
+std::unique_ptr<protocol::Array<protocol::Debugger::SearchMatch>> searchInTextByLines(V8InspectorSession* session, const String16& text, const String16& query, const bool caseSensitive, const bool isRegex)
+{
+ std::unique_ptr<protocol::Array<protocol::Debugger::SearchMatch>> result = protocol::Array<protocol::Debugger::SearchMatch>::create();
+ std::unique_ptr<V8Regex> regex = createSearchRegex(static_cast<V8InspectorSessionImpl*>(session)->debugger(), query, caseSensitive, isRegex);
+ protocol::Vector<std::pair<int, String16>> matches = scriptRegexpMatchesByLines(*regex.get(), text);
+
+ for (const auto& match : matches)
+ result->addItem(buildObjectForSearchMatch(match.first, match.second));
+
+ return result;
+}
+
+} // namespace V8ContentSearchUtil
+
+std::unique_ptr<protocol::Value> toProtocolValue(v8::Local<v8::Context> context, v8::Local<v8::Value> value, int maxDepth)
+{
+ if (value.IsEmpty()) {
+ NOTREACHED();
+ return nullptr;
+ }
+
+ if (!maxDepth)
+ return nullptr;
+ maxDepth--;
+
+ if (value->IsNull() || value->IsUndefined())
+ return protocol::Value::null();
+ if (value->IsBoolean())
+ return protocol::FundamentalValue::create(value.As<v8::Boolean>()->Value());
+ if (value->IsNumber())
+ return protocol::FundamentalValue::create(value.As<v8::Number>()->Value());
+ if (value->IsString())
+ return protocol::StringValue::create(toProtocolString(value.As<v8::String>()));
+ if (value->IsArray()) {
+ v8::Local<v8::Array> array = value.As<v8::Array>();
+ std::unique_ptr<protocol::ListValue> inspectorArray = protocol::ListValue::create();
+ uint32_t length = array->Length();
+ for (uint32_t i = 0; i < length; i++) {
+ v8::Local<v8::Value> value;
+ if (!array->Get(context, i).ToLocal(&value))
+ return nullptr;
+ std::unique_ptr<protocol::Value> element = toProtocolValue(context, value, maxDepth);
+ if (!element)
+ return nullptr;
+ inspectorArray->pushValue(std::move(element));
+ }
+ return std::move(inspectorArray);
+ }
+ if (value->IsObject()) {
+ std::unique_ptr<protocol::DictionaryValue> jsonObject = protocol::DictionaryValue::create();
+ v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);
+ v8::Local<v8::Array> propertyNames;
+ if (!object->GetPropertyNames(context).ToLocal(&propertyNames))
+ return nullptr;
+ uint32_t length = propertyNames->Length();
+ for (uint32_t i = 0; i < length; i++) {
+ v8::Local<v8::Value> name;
+ if (!propertyNames->Get(context, i).ToLocal(&name))
+ return nullptr;
+ // FIXME(yurys): v8::Object should support GetOwnPropertyNames
+ if (name->IsString()) {
+ v8::Maybe<bool> hasRealNamedProperty = object->HasRealNamedProperty(context, v8::Local<v8::String>::Cast(name));
+ if (!hasRealNamedProperty.IsJust() || !hasRealNamedProperty.FromJust())
+ continue;
+ }
+ v8::Local<v8::String> propertyName;
+ if (!name->ToString(context).ToLocal(&propertyName))
+ continue;
+ v8::Local<v8::Value> property;
+ if (!object->Get(context, name).ToLocal(&property))
+ return nullptr;
+ std::unique_ptr<protocol::Value> propertyValue = toProtocolValue(context, property, maxDepth);
+ if (!propertyValue)
+ return nullptr;
+ jsonObject->setValue(toProtocolString(propertyName), std::move(propertyValue));
+ }
+ return std::move(jsonObject);
+ }
+ NOTREACHED();
+ return nullptr;
+}
+
+} // namespace blink
diff --git a/deps/v8_inspector/platform/v8_inspector/V8StringUtil.h b/deps/v8_inspector/platform/v8_inspector/V8StringUtil.h
new file mode 100644
index 0000000000..c1c506baae
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/V8StringUtil.h
@@ -0,0 +1,22 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8StringUtil_h
+#define V8StringUtil_h
+
+#include "platform/inspector_protocol/String16.h"
+#include <v8.h>
+
+namespace blink {
+
+v8::Local<v8::String> toV8String(v8::Isolate*, const String16&);
+v8::Local<v8::String> toV8StringInternalized(v8::Isolate*, const String16&);
+
+String16 toProtocolString(v8::Local<v8::String>);
+String16 toProtocolStringWithTypeCheck(v8::Local<v8::Value>);
+
+} // namespace blink
+
+
+#endif // !defined(V8StringUtil_h)
diff --git a/deps/v8_inspector/platform/v8_inspector/build/rjsmin.py b/deps/v8_inspector/platform/v8_inspector/build/rjsmin.py
new file mode 100755
index 0000000000..8357a6dcc1
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/build/rjsmin.py
@@ -0,0 +1,295 @@
+#!/usr/bin/env python
+#
+# Copyright 2011 - 2013
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+r"""
+=====================
+ Javascript Minifier
+=====================
+
+rJSmin is a javascript minifier written in python.
+
+The minifier is based on the semantics of `jsmin.c by Douglas Crockford`_\.
+
+The module is a re-implementation aiming for speed, so it can be used at
+runtime (rather than during a preprocessing step). Usually it produces the
+same results as the original ``jsmin.c``. It differs in the following ways:
+
+- there is no error detection: unterminated string, regex and comment
+ literals are treated as regular javascript code and minified as such.
+- Control characters inside string and regex literals are left untouched; they
+ are not converted to spaces (nor to \n)
+- Newline characters are not allowed inside string and regex literals, except
+ for line continuations in string literals (ECMA-5).
+- "return /regex/" is recognized correctly.
+- "+ +" and "- -" sequences are not collapsed to '++' or '--'
+- Newlines before ! operators are removed more sensibly
+- rJSmin does not handle streams, but only complete strings. (However, the
+ module provides a "streamy" interface).
+
+Since most parts of the logic are handled by the regex engine it's way
+faster than the original python port of ``jsmin.c`` by Baruch Even. The speed
+factor varies between about 6 and 55 depending on input and python version
+(it gets faster the more compressed the input already is). Compared to the
+speed-refactored python port by Dave St.Germain the performance gain is less
+dramatic but still between 1.2 and 7. See the docs/BENCHMARKS file for
+details.
+
+rjsmin.c is a reimplementation of rjsmin.py in C and speeds it up even more.
+
+Both python 2 and python 3 are supported.
+
+.. _jsmin.c by Douglas Crockford:
+ http://www.crockford.com/javascript/jsmin.c
+"""
+__author__ = "Andr\xe9 Malo"
+__author__ = getattr(__author__, 'decode', lambda x: __author__)('latin-1')
+__docformat__ = "restructuredtext en"
+__license__ = "Apache License, Version 2.0"
+__version__ = '1.0.7'
+__all__ = ['jsmin']
+
+import re as _re
+
+
+def _make_jsmin(python_only=False):
+ """
+ Generate JS minifier based on `jsmin.c by Douglas Crockford`_
+
+ .. _jsmin.c by Douglas Crockford:
+ http://www.crockford.com/javascript/jsmin.c
+
+ :Parameters:
+ `python_only` : ``bool``
+ Use only the python variant. If true, the c extension is not even
+ tried to be loaded.
+
+ :Return: Minifier
+ :Rtype: ``callable``
+ """
+ # pylint: disable = R0912, R0914, W0612
+ if not python_only:
+ try:
+ import _rjsmin
+ except ImportError:
+ pass
+ else:
+ return _rjsmin.jsmin
+ try:
+ xrange
+ except NameError:
+ xrange = range # pylint: disable = W0622
+
+ space_chars = r'[\000-\011\013\014\016-\040]'
+
+ line_comment = r'(?://[^\r\n]*)'
+ space_comment = r'(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)'
+ string1 = \
+ r'(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|\r)[^\047\\\r\n]*)*\047)'
+ string2 = r'(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|\r)[^"\\\r\n]*)*")'
+ strings = r'(?:%s|%s)' % (string1, string2)
+
+ charclass = r'(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\])'
+ nospecial = r'[^/\\\[\r\n]'
+ regex = r'(?:/(?![\r\n/*])%s*(?:(?:\\[^\r\n]|%s)%s*)*/)' % (
+ nospecial, charclass, nospecial)
+ space = r'(?:%s|%s)' % (space_chars, space_comment)
+ newline = r'(?:%s?[\r\n])' % line_comment
+
+ def fix_charclass(result):
+ """ Fixup string of chars to fit into a regex char class """
+ pos = result.find('-')
+ if pos >= 0:
+ result = r'%s%s-' % (result[:pos], result[pos + 1:])
+
+ def sequentize(string):
+ """
+ Notate consecutive characters as sequence
+
+ (1-4 instead of 1234)
+ """
+ first, last, result = None, None, []
+ for char in map(ord, string):
+ if last is None:
+ first = last = char
+ elif last + 1 == char:
+ last = char
+ else:
+ result.append((first, last))
+ first = last = char
+ if last is not None:
+ result.append((first, last))
+ return ''.join(['%s%s%s' % (
+ chr(first),
+ last > first + 1 and '-' or '',
+ last != first and chr(last) or '') for first, last in result])
+
+ return _re.sub(r'([\000-\040\047])', # for better portability
+ lambda m: '\\%03o' % ord(m.group(1)), (sequentize(result)
+ .replace('\\', '\\\\')
+ .replace('[', '\\[')
+ .replace(']', '\\]')))
+
+ def id_literal_(what):
+ """ Make id_literal like char class """
+ match = _re.compile(what).match
+ result = ''.join([chr(c) for c in xrange(127) if not match(chr(c))])
+ return '[^%s]' % fix_charclass(result)
+
+ def not_id_literal_(keep):
+ """ Make negated id_literal like char class """
+ match = _re.compile(id_literal_(keep)).match
+ result = ''.join([chr(c) for c in xrange(127) if not match(chr(c))])
+ return r'[%s]' % fix_charclass(result)
+
+ not_id_literal = not_id_literal_(r'[a-zA-Z0-9_$]')
+ preregex1 = r'[(,=:\[!&|?{};\r\n]'
+ preregex2 = r'%(not_id_literal)sreturn' % locals()
+
+ id_literal = id_literal_(r'[a-zA-Z0-9_$]')
+ id_literal_open = id_literal_(r'[a-zA-Z0-9_${\[(!+-]')
+ id_literal_close = id_literal_(r'[a-zA-Z0-9_$}\])"\047+-]')
+
+ dull = r'[^\047"/\000-\040]'
+
+ space_sub = _re.compile((
+ r'(%(dull)s+)'
+ r'|(%(strings)s%(dull)s*)'
+ r'|(?<=%(preregex1)s)'
+ r'%(space)s*(?:%(newline)s%(space)s*)*'
+ r'(%(regex)s%(dull)s*)'
+ r'|(?<=%(preregex2)s)'
+ r'%(space)s*(?:%(newline)s%(space)s)*'
+ r'(%(regex)s%(dull)s*)'
+ r'|(?<=%(id_literal_close)s)'
+ r'%(space)s*(?:(%(newline)s)%(space)s*)+'
+ r'(?=%(id_literal_open)s)'
+ r'|(?<=%(id_literal)s)(%(space)s)+(?=%(id_literal)s)'
+ r'|(?<=\+)(%(space)s)+(?=\+)'
+ r'|(?<=-)(%(space)s)+(?=-)'
+ r'|%(space)s+'
+ r'|(?:%(newline)s%(space)s*)+') % locals()).sub
+ #print space_sub.__self__.pattern
+
+ def space_subber(match):
+ """ Substitution callback """
+ # pylint: disable = C0321, R0911
+ groups = match.groups()
+ if groups[0]:
+ return groups[0]
+ elif groups[1]:
+ return groups[1]
+ elif groups[2]:
+ return groups[2]
+ elif groups[3]:
+ return groups[3]
+ elif groups[4]:
+ return '\n'
+ elif groups[5] or groups[6] or groups[7]:
+ return ' '
+ else:
+ return ''
+
+ def jsmin(script): # pylint: disable = W0621
+ r"""
+ Minify javascript based on `jsmin.c by Douglas Crockford`_\.
+
+ Instead of parsing the stream char by char, it uses a regular
+ expression approach which minifies the whole script with one big
+ substitution regex.
+
+ .. _jsmin.c by Douglas Crockford:
+ http://www.crockford.com/javascript/jsmin.c
+
+ :Parameters:
+ `script` : ``str``
+ Script to minify
+
+ :Return: Minified script
+ :Rtype: ``str``
+ """
+ return space_sub(space_subber, '\n%s\n' % script).strip()
+
+ return jsmin
+
+jsmin = _make_jsmin()
+
+
+def jsmin_for_posers(script):
+ r"""
+ Minify javascript based on `jsmin.c by Douglas Crockford`_\.
+
+ Instead of parsing the stream char by char, it uses a regular
+ expression approach which minifies the whole script with one big
+ substitution regex.
+
+ .. _jsmin.c by Douglas Crockford:
+ http://www.crockford.com/javascript/jsmin.c
+
+ :Warning: This function is the digest of a _make_jsmin() call. It just
+ utilizes the resulting regex. It's just for fun here and may
+ vanish any time. Use the `jsmin` function instead.
+
+ :Parameters:
+ `script` : ``str``
+ Script to minify
+
+ :Return: Minified script
+ :Rtype: ``str``
+ """
+ def subber(match):
+ """ Substitution callback """
+ groups = match.groups()
+ return (
+ groups[0] or
+ groups[1] or
+ groups[2] or
+ groups[3] or
+ (groups[4] and '\n') or
+ (groups[5] and ' ') or
+ (groups[6] and ' ') or
+ (groups[7] and ' ') or
+ '')
+
+ return _re.sub(
+ r'([^\047"/\000-\040]+)|((?:(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]|\r?'
+ r'\n|\r)[^\047\\\r\n]*)*\047)|(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|'
+ r'\r)[^"\\\r\n]*)*"))[^\047"/\000-\040]*)|(?<=[(,=:\[!&|?{};\r\n])(?'
+ r':[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*'
+ r'(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*'
+ r'[^*]*\*+(?:[^/*][^*]*\*+)*/))*)*((?:/(?![\r\n/*])[^/\\\[\r\n]*(?:('
+ r'?:\\[^\r\n]|(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\]))[^/\\\['
+ r'\r\n]*)*/)[^\047"/\000-\040]*)|(?<=[\000-#%-,./:-@\[-^`{-~-]return'
+ r')(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/'
+ r'))*(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:'
+ r'/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))*((?:/(?![\r\n/*])[^/\\\[\r\n]*(?'
+ r':(?:\\[^\r\n]|(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\]))[^/'
+ r'\\\[\r\n]*)*/)[^\047"/\000-\040]*)|(?<=[^\000-!#%&(*,./:-@\[\\^`{|'
+ r'~])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)'
+ r'*/))*(?:((?:(?://[^\r\n]*)?[\r\n]))(?:[\000-\011\013\014\016-\040]'
+ r'|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+(?=[^\000-\040"#%-\047)*,./'
+ r':-@\\-^`|-~])|(?<=[^\000-#%-,./:-@\[-^`{-~-])((?:[\000-\011\013\01'
+ r'4\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=[^\000-#%-,./:'
+ r'-@\[-^`{-~-])|(?<=\+)((?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*'
+ r'\*+(?:[^/*][^*]*\*+)*/)))+(?=\+)|(?<=-)((?:[\000-\011\013\014\016-'
+ r'\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=-)|(?:[\000-\011\013'
+ r'\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))+|(?:(?:(?://[^'
+ r'\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^'
+ r'/*][^*]*\*+)*/))*)+', subber, '\n%s\n' % script).strip()
+
+
+if __name__ == '__main__':
+ import sys as _sys
+ _sys.stdout.write(jsmin(_sys.stdin.read()))
diff --git a/deps/v8_inspector/platform/v8_inspector/build/xxd.py b/deps/v8_inspector/platform/v8_inspector/build/xxd.py
new file mode 100644
index 0000000000..635d80c7d4
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/build/xxd.py
@@ -0,0 +1,28 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Represent a file as a C++ constant string.
+
+Usage:
+python xxd.py VAR SOURCE DEST
+"""
+
+
+import sys
+import rjsmin
+
+
+def main():
+ variable_name, input_filename, output_filename = sys.argv[1:]
+ with open(input_filename) as input_file:
+ input_text = input_file.read()
+ input_text = rjsmin.jsmin(input_text)
+ hex_values = ['0x{0:02x}'.format(ord(char)) for char in input_text]
+ const_declaration = 'const char %s[] = {\n%s\n};\n' % (
+ variable_name, ', '.join(hex_values))
+ with open(output_filename, 'w') as output_file:
+ output_file.write(const_declaration)
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/deps/v8_inspector/platform/v8_inspector/debugger_script_externs.js b/deps/v8_inspector/platform/v8_inspector/debugger_script_externs.js
new file mode 100644
index 0000000000..25d0754279
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/debugger_script_externs.js
@@ -0,0 +1,556 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/** @typedef {{
+ type: string,
+ object: !Object,
+ name: (string|undefined),
+ startLocation: (!RawLocation|undefined),
+ endLocation: (!RawLocation|undefined)
+ }} */
+var Scope;
+
+/** @typedef {{
+ scriptId: string,
+ lineNumber: number,
+ columnNumber: number
+ }} */
+var RawLocation;
+
+/** @typedef {{
+ function: function(),
+ functionName: string,
+ status: string,
+ location: (!RawLocation|undefined)
+ }} */
+var GeneratorObjectDetails;
+
+/** @typedef {{
+ id: number,
+ name: string,
+ sourceURL: (string|undefined),
+ sourceMappingURL: (string|undefined),
+ source: string,
+ startLine: number,
+ endLine: number,
+ startColumn: number,
+ endColumn: number,
+ executionContextId: number,
+ isContentScript: boolean,
+ isInternalScript: boolean
+ }} */
+var FormattedScript;
+
+/** @typedef {{
+ functionName: string,
+ location: !RawLocation,
+ this: !Object,
+ scopeChain: !Array<!Scope>,
+ functionLocation: (RawLocation|undefined),
+ returnValue: (*|undefined)
+ }} */
+var JavaScriptCallFrameDetails;
+
+/** @typedef {{
+ sourceID: function():(number|undefined),
+ line: function():number,
+ column: function():number,
+ thisObject: !Object,
+ evaluate: function(string):*,
+ restart: function():undefined,
+ setVariableValue: function(number, string, *):undefined,
+ isAtReturn: boolean,
+ details: function():!JavaScriptCallFrameDetails
+ }} */
+var JavaScriptCallFrame;
+
+/** @interface */
+function DebugClass()
+{
+ /** @type {!LiveEditClass} */
+ this.LiveEdit;
+}
+
+DebugClass.prototype.setBreakOnException = function() {}
+
+DebugClass.prototype.clearBreakOnException = function() {}
+
+DebugClass.prototype.setBreakOnUncaughtException = function() {}
+
+DebugClass.prototype.clearBreakOnUncaughtException = function() {}
+
+DebugClass.prototype.clearStepping = function() {}
+
+DebugClass.prototype.clearAllBreakPoints = function() {}
+
+/** @return {!Array<!Script>} */
+DebugClass.prototype.scripts = function() {}
+
+/**
+ * @param {number} scriptId
+ * @param {number=} line
+ * @param {number=} column
+ * @param {string=} condition
+ * @param {string=} groupId
+ * @param {Debug.BreakPositionAlignment=} positionAlignment
+ */
+DebugClass.prototype.setScriptBreakPointById = function(scriptId, line, column, condition, groupId, positionAlignment) {}
+
+/**
+ * @param {number} breakId
+ * @return {!Array<!SourceLocation>}
+ */
+DebugClass.prototype.findBreakPointActualLocations = function(breakId) {}
+
+/**
+ * @param {number} breakId
+ * @param {boolean} remove
+ * @return {!BreakPoint|undefined}
+ */
+DebugClass.prototype.findBreakPoint = function(breakId, remove) {}
+
+/** @return {!DebuggerFlags} */
+DebugClass.prototype.debuggerFlags = function() {}
+
+/** @type {!DebugClass} */
+var Debug;
+
+
+/** @enum */
+Debug.BreakPositionAlignment = {
+ Statement: 0,
+ BreakPosition: 1
+};
+
+/** @enum */
+Debug.StepAction = { StepOut: 0,
+ StepNext: 1,
+ StepIn: 2,
+ StepFrame: 3 };
+
+/** @enum */
+Debug.ScriptCompilationType = { Host: 0,
+ Eval: 1,
+ JSON: 2 };
+
+
+/** @interface */
+function DebuggerFlag() {}
+
+/** @param {boolean} value */
+DebuggerFlag.prototype.setValue = function(value) {}
+
+
+/** @interface */
+function DebuggerFlags()
+{
+ /** @type {!DebuggerFlag} */
+ this.breakPointsActive;
+}
+
+
+/** @interface */
+function LiveEditClass() {}
+
+/**
+ * @param {!Script} script
+ * @param {string} newSource
+ * @param {boolean} previewOnly
+ * @return {!{stack_modified: (boolean|undefined)}}
+ */
+LiveEditClass.prototype.SetScriptSource = function(script, newSource, previewOnly, change_log) {}
+
+
+/** @interface */
+function LiveEditErrorDetails()
+{
+ /** @type {string} */
+ this.syntaxErrorMessage;
+ /** @type {!{start: !{line: number, column: number}}} */
+ this.position;
+}
+
+
+/** @interface */
+function BreakpointInfo()
+{
+ /** @type {number} */
+ this.breakpointId;
+ /** @type {number} */
+ this.sourceID;
+ /** @type {number|undefined} */
+ this.lineNumber;
+ /** @type {number|undefined} */
+ this.columnNumber;
+ /** @type {string|undefined} */
+ this.condition;
+ /** @type {boolean|undefined} */
+ this.interstatementLocation;
+}
+
+
+/** @interface */
+function BreakPoint() {}
+
+/** @return {!BreakPoint|undefined} */
+BreakPoint.prototype.script_break_point = function() {}
+
+/** @return {number} */
+BreakPoint.prototype.number = function() {}
+
+
+/** @interface */
+function CompileEvent() {}
+
+/** @return {!ScriptMirror} */
+CompileEvent.prototype.script = function() {}
+
+
+/** @interface */
+function BreakEvent() {}
+
+/** @return {!Array<!BreakPoint>|undefined} */
+BreakEvent.prototype.breakPointsHit = function() {}
+
+
+/** @interface */
+function ExecutionState() {}
+
+/** @param {!Debug.StepAction} action */
+ExecutionState.prototype.prepareStep = function(action) {}
+
+/**
+ * @param {string} source
+ * @param {boolean} disableBreak
+ * @param {*=} additionalContext
+ */
+ExecutionState.prototype.evaluateGlobal = function(source, disableBreak, additionalContext) {}
+
+/** @return {number} */
+ExecutionState.prototype.frameCount = function() {}
+
+/**
+ * @param {number} index
+ * @return {!FrameMirror}
+ */
+ExecutionState.prototype.frame = function(index) {}
+
+/** @param {number} index */
+ExecutionState.prototype.setSelectedFrame = function(index) {}
+
+/** @return {number} */
+ExecutionState.prototype.selectedFrame = function() {}
+
+
+/** @enum */
+var ScopeType = { Global: 0,
+ Local: 1,
+ With: 2,
+ Closure: 3,
+ Catch: 4,
+ Block: 5,
+ Script: 6 };
+
+
+/** @interface */
+function SourceLocation()
+{
+ /** @type {number} */
+ this.script;
+ /** @type {number} */
+ this.position;
+ /** @type {number} */
+ this.line;
+ /** @type {number} */
+ this.column;
+ /** @type {number} */
+ this.start;
+ /** @type {number} */
+ this.end;
+}
+
+
+/** @interface */
+function Script()
+{
+ /** @type {number} */
+ this.id;
+ /** @type {string|undefined} */
+ this.context_data;
+ /** @type {string|undefined} */
+ this.source_url;
+ /** @type {string|undefined} */
+ this.source_mapping_url;
+ /** @type {boolean} */
+ this.is_debugger_script;
+ /** @type {string} */
+ this.source;
+ /** @type {!Array<number>} */
+ this.line_ends;
+ /** @type {number} */
+ this.line_offset;
+ /** @type {number} */
+ this.column_offset;
+}
+
+/** @return {string} */
+Script.prototype.nameOrSourceURL = function() {}
+
+/** @return {!Debug.ScriptCompilationType} */
+Script.prototype.compilationType = function() {}
+
+
+/** @interface */
+function ScopeDetails() {}
+
+/** @return {!Object} */
+ScopeDetails.prototype.object = function() {}
+
+/** @return {string|undefined} */
+ScopeDetails.prototype.name = function() {}
+
+
+/** @interface */
+function FrameDetails() {}
+
+/** @return {!Object} */
+FrameDetails.prototype.receiver = function() {}
+
+/** @return {function()} */
+FrameDetails.prototype.func = function() {}
+
+/** @return {boolean} */
+FrameDetails.prototype.isAtReturn = function() {}
+
+/** @return {number} */
+FrameDetails.prototype.sourcePosition = function() {}
+
+/** @return {*} */
+FrameDetails.prototype.returnValue = function() {}
+
+/** @return {number} */
+FrameDetails.prototype.scopeCount = function() {}
+
+
+/** @param {boolean} value */
+function ToggleMirrorCache(value) {}
+
+/**
+ * @param {*} value
+ * @param {boolean=} transient
+ * @return {!Mirror}
+ */
+function MakeMirror(value, transient) {}
+
+
+/** @interface */
+function Mirror() {}
+
+/** @return {boolean} */
+Mirror.prototype.isFunction = function() {}
+
+/** @return {boolean} */
+Mirror.prototype.isGenerator = function() {}
+
+/** @return {boolean} */
+Mirror.prototype.isMap = function() {}
+
+/** @return {boolean} */
+Mirror.prototype.isSet = function() {}
+
+/** @return {boolean} */
+Mirror.prototype.isIterator = function() {}
+
+
+/**
+ * @interface
+ * @extends {Mirror}
+ */
+function ObjectMirror() {}
+
+/** @return {!Array<!PropertyMirror>} */
+ObjectMirror.prototype.properties = function() {}
+
+
+/**
+ * @interface
+ * @extends {ObjectMirror}
+ */
+function FunctionMirror () {}
+
+/** @return {number} */
+FunctionMirror.prototype.scopeCount = function() {}
+
+/**
+ * @param {number} index
+ * @return {!ScopeMirror|undefined}
+ */
+FunctionMirror.prototype.scope = function(index) {}
+
+/** @return {boolean} */
+FunctionMirror.prototype.resolved = function() {}
+
+/** @return {function()} */
+FunctionMirror.prototype.value = function() {}
+
+/** @return {string} */
+FunctionMirror.prototype.debugName = function() {}
+
+/** @return {!ScriptMirror|undefined} */
+FunctionMirror.prototype.script = function() {}
+
+/** @return {!SourceLocation|undefined} */
+FunctionMirror.prototype.sourceLocation = function() {}
+
+/** @return {!ContextMirror|undefined} */
+FunctionMirror.prototype.context = function() {}
+
+/**
+ * @constructor
+ * @param {*} value
+ */
+function UnresolvedFunctionMirror(value) {}
+
+
+/**
+ * @interface
+ * @extends {ObjectMirror}
+ */
+function MapMirror () {}
+
+/**
+ * @param {number=} limit
+ * @return {!Array<!{key: *, value: *}>}
+ */
+MapMirror.prototype.entries = function(limit) {}
+
+
+/**
+ * @interface
+ * @extends {ObjectMirror}
+ */
+function SetMirror () {}
+
+/**
+ * @param {number=} limit
+ * @return {!Array<*>}
+ */
+SetMirror.prototype.values = function(limit) {}
+
+
+/**
+ * @interface
+ * @extends {ObjectMirror}
+ */
+function IteratorMirror () {}
+
+/**
+ * @param {number=} limit
+ * @return {!Array<*>}
+ */
+IteratorMirror.prototype.preview = function(limit) {}
+
+
+/**
+ * @interface
+ * @extends {ObjectMirror}
+ */
+function GeneratorMirror () {}
+
+/** @return {string} */
+GeneratorMirror.prototype.status = function() {}
+
+/** @return {!SourceLocation|undefined} */
+GeneratorMirror.prototype.sourceLocation = function() {}
+
+/** @return {!FunctionMirror} */
+GeneratorMirror.prototype.func = function() {}
+
+
+/**
+ * @interface
+ * @extends {Mirror}
+ */
+function PropertyMirror()
+{
+ /** @type {*} */
+ this.value_;
+}
+
+/** @return {!Mirror} */
+PropertyMirror.prototype.value = function() {}
+
+/** @return {string} */
+PropertyMirror.prototype.name = function() {}
+
+
+/**
+ * @interface
+ * @extends {Mirror}
+ */
+function FrameMirror() {}
+
+/**
+ * @param {boolean=} ignoreNestedScopes
+ * @return {!Array<!ScopeMirror>}
+ */
+FrameMirror.prototype.allScopes = function(ignoreNestedScopes) {}
+
+/** @return {!FrameDetails} */
+FrameMirror.prototype.details = function() {}
+
+/**
+ * @param {string} source
+ * @param {boolean} disableBreak
+ */
+FrameMirror.prototype.evaluate = function(source, disableBreak) {}
+
+FrameMirror.prototype.restart = function() {}
+
+/** @param {number} index */
+FrameMirror.prototype.scope = function(index) {}
+
+
+/**
+ * @interface
+ * @extends {Mirror}
+ */
+function ScriptMirror() {}
+
+/** @return {!Script} */
+ScriptMirror.prototype.value = function() {}
+
+/** @return {number} */
+ScriptMirror.prototype.id = function() {}
+
+/**
+ * @param {number} position
+ * @param {boolean=} includeResourceOffset
+ */
+ScriptMirror.prototype.locationFromPosition = function(position, includeResourceOffset) {}
+
+
+/**
+ * @interface
+ * @extends {Mirror}
+ */
+function ScopeMirror() {}
+
+/** @return {!ScopeDetails} */
+ScopeMirror.prototype.details = function() {}
+
+/**
+ * @param {string} name
+ * @param {*} newValue
+ */
+ScopeMirror.prototype.setVariableValue = function(name, newValue) {}
+
+/**
+ * @interface
+ * @extends {Mirror}
+ */
+function ContextMirror() {}
+
+/** @return {string|undefined} */
+ContextMirror.prototype.data = function() {}
diff --git a/deps/v8_inspector/platform/v8_inspector/injected_script_externs.js b/deps/v8_inspector/platform/v8_inspector/injected_script_externs.js
new file mode 100644
index 0000000000..a543e5471f
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/injected_script_externs.js
@@ -0,0 +1,97 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/** @interface */
+function InjectedScriptHostClass()
+{
+}
+
+/**
+ * @param {*} objectId
+ * @param {!Object} hints
+ */
+InjectedScriptHostClass.prototype.inspect = function(objectId, hints) {}
+
+/**
+ * @param {*} obj
+ * @return {string}
+ */
+InjectedScriptHostClass.prototype.internalConstructorName = function(obj) {}
+
+/**
+ * @param {*} obj
+ * @return {boolean}
+ */
+InjectedScriptHostClass.prototype.formatAccessorsAsProperties = function(obj) {}
+
+/**
+ * @param {*} obj
+ * @return {string}
+ */
+InjectedScriptHostClass.prototype.subtype = function(obj) {}
+
+/**
+ * @param {*} obj
+ * @return {boolean}
+ */
+InjectedScriptHostClass.prototype.isTypedArray = function(obj) {}
+
+/**
+ * @param {!Object} obj
+ * @return {?Array.<*>}
+ */
+InjectedScriptHostClass.prototype.collectionEntries = function(obj) {}
+
+/**
+ * @param {*} obj
+ * @return {!Array.<*>}
+ */
+InjectedScriptHostClass.prototype.getInternalProperties = function(obj) {}
+
+/**
+ * @param {!EventTarget} target
+ * @return {!Object|undefined}
+ */
+InjectedScriptHostClass.prototype.getEventListeners = function(target) {}
+
+/**
+ * @param {!Function} fn
+ * @param {*} receiver
+ * @param {!Array.<*>=} argv
+ * @return {*}
+ */
+InjectedScriptHostClass.prototype.suppressWarningsAndCallFunction = function(fn, receiver, argv) {}
+
+/**
+ * @param {!Object} obj
+ * @param {string} key
+ * @param {*} value
+ */
+InjectedScriptHostClass.prototype.setNonEnumProperty = function(obj, key, value) {}
+
+/**
+ * @param {*} value
+ * @param {string} groupName
+ * @return {number}
+ */
+InjectedScriptHostClass.prototype.bind = function(value, groupName) {}
+
+/**
+ * @param {!Object} object
+ * @return {!Object}
+ */
+InjectedScriptHostClass.prototype.proxyTargetValue = function(object) {}
+
+/**
+ * @param {!Object} object
+ * @return {Object|undefined}
+ */
+InjectedScriptHostClass.prototype.prototype = function(object) {}
+
+/** @type {!InjectedScriptHostClass} */
+var InjectedScriptHost;
+/** @type {!Window} */
+var inspectedGlobalObject;
+/** @type {number} */
+var injectedScriptId;
diff --git a/deps/v8_inspector/platform/v8_inspector/public/ConsoleAPITypes.h b/deps/v8_inspector/platform/v8_inspector/public/ConsoleAPITypes.h
new file mode 100644
index 0000000000..59487b86a9
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/public/ConsoleAPITypes.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ConsoleAPITypes_h
+#define ConsoleAPITypes_h
+
+namespace blink {
+
+enum MessageType {
+ LogMessageType = 1,
+ DirMessageType,
+ DirXMLMessageType,
+ TableMessageType,
+ TraceMessageType,
+ StartGroupMessageType,
+ StartGroupCollapsedMessageType,
+ EndGroupMessageType,
+ ClearMessageType,
+ AssertMessageType,
+ TimeEndMessageType,
+ CountMessageType
+};
+
+} // namespace blink
+
+#endif // ConsoleAPITypes_h
diff --git a/deps/v8_inspector/platform/v8_inspector/public/ConsoleTypes.h b/deps/v8_inspector/platform/v8_inspector/public/ConsoleTypes.h
new file mode 100644
index 0000000000..fb06fb8ed0
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/public/ConsoleTypes.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ConsoleTypes_h
+#define ConsoleTypes_h
+
+namespace blink {
+
+enum MessageSource {
+ XMLMessageSource,
+ JSMessageSource,
+ NetworkMessageSource,
+ ConsoleAPIMessageSource,
+ StorageMessageSource,
+ AppCacheMessageSource,
+ RenderingMessageSource,
+ SecurityMessageSource,
+ OtherMessageSource,
+ DeprecationMessageSource,
+};
+
+enum MessageLevel {
+ DebugMessageLevel = 4,
+ LogMessageLevel = 1,
+ InfoMessageLevel = 5,
+ WarningMessageLevel = 2,
+ ErrorMessageLevel = 3,
+ RevokedErrorMessageLevel = 6
+};
+
+} // namespace blink
+
+#endif // ConsoleTypes_h
diff --git a/deps/v8_inspector/platform/v8_inspector/public/V8ContentSearchUtil.h b/deps/v8_inspector/platform/v8_inspector/public/V8ContentSearchUtil.h
new file mode 100644
index 0000000000..565fc9673d
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/public/V8ContentSearchUtil.h
@@ -0,0 +1,26 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8ContentSearchUtil_h
+#define V8ContentSearchUtil_h
+
+#include "platform/PlatformExport.h"
+#include "platform/inspector_protocol/String16.h"
+#include "platform/inspector_protocol/TypeBuilder.h"
+
+namespace blink {
+
+class V8InspectorSession;
+
+namespace V8ContentSearchUtil {
+
+PLATFORM_EXPORT String16 findSourceURL(const String16& content, bool multiline, bool* deprecated = nullptr);
+PLATFORM_EXPORT String16 findSourceMapURL(const String16& content, bool multiline, bool* deprecated = nullptr);
+PLATFORM_EXPORT std::unique_ptr<protocol::Array<protocol::Debugger::SearchMatch>> searchInTextByLines(V8InspectorSession*, const String16& text, const String16& query, const bool caseSensitive, const bool isRegex);
+
+}
+
+}
+
+#endif // !defined(V8ContentSearchUtil_h)
diff --git a/deps/v8_inspector/platform/v8_inspector/public/V8ContextInfo.h b/deps/v8_inspector/platform/v8_inspector/public/V8ContextInfo.h
new file mode 100644
index 0000000000..43ce46f9f6
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/public/V8ContextInfo.h
@@ -0,0 +1,42 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8ContextInfo_h
+#define V8ContextInfo_h
+
+#include "platform/inspector_protocol/Collections.h"
+#include "platform/inspector_protocol/String16.h"
+
+#include <v8.h>
+
+namespace blink {
+
+class V8ContextInfo {
+public:
+ V8ContextInfo(v8::Local<v8::Context> context, int contextGroupId, bool isDefault, const String16& origin, const String16& humanReadableName, const String16& frameId, bool hasMemoryOnConsole)
+ : context(context)
+ , contextGroupId(contextGroupId)
+ , isDefault(isDefault)
+ , origin(origin)
+ , humanReadableName(humanReadableName)
+ , frameId(frameId)
+ , hasMemoryOnConsole(hasMemoryOnConsole)
+ {
+ }
+
+ v8::Local<v8::Context> context;
+ // Each v8::Context is a part of a group. The group id is used to find appropriate
+ // V8DebuggerAgent to notify about events in the context.
+ // |contextGroupId| must be non-0.
+ int contextGroupId;
+ bool isDefault;
+ const String16 origin;
+ const String16 humanReadableName;
+ const String16 frameId;
+ bool hasMemoryOnConsole;
+};
+
+} // namespace blink
+
+#endif // V8ContextInfo_h
diff --git a/deps/v8_inspector/platform/v8_inspector/public/V8Debugger.h b/deps/v8_inspector/platform/v8_inspector/public/V8Debugger.h
new file mode 100644
index 0000000000..c4fa6cfd78
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/public/V8Debugger.h
@@ -0,0 +1,65 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8Debugger_h
+#define V8Debugger_h
+
+#include "platform/PlatformExport.h"
+#include "platform/inspector_protocol/Frontend.h"
+#include "wtf/PtrUtil.h"
+
+#include <v8.h>
+
+namespace blink {
+
+class V8ContextInfo;
+class V8DebuggerClient;
+class V8InspectorSession;
+class V8StackTrace;
+
+namespace protocol {
+class DictionaryValue;
+}
+
+class PLATFORM_EXPORT V8Debugger {
+public:
+ template <typename T>
+ class Agent {
+ public:
+ virtual void setInspectorState(protocol::DictionaryValue*) = 0;
+ virtual void setFrontend(T*) = 0;
+ virtual void clearFrontend() = 0;
+ virtual void restore() = 0;
+ };
+
+ static std::unique_ptr<V8Debugger> create(v8::Isolate*, V8DebuggerClient*);
+ virtual ~V8Debugger() { }
+
+ // TODO(dgozman): make this non-static?
+ static int contextId(v8::Local<v8::Context>);
+
+ virtual void contextCreated(const V8ContextInfo&) = 0;
+ virtual void contextDestroyed(v8::Local<v8::Context>) = 0;
+ // TODO(dgozman): remove this one.
+ virtual void resetContextGroup(int contextGroupId) = 0;
+ virtual void willExecuteScript(v8::Local<v8::Context>, int scriptId) = 0;
+ virtual void didExecuteScript(v8::Local<v8::Context>) = 0;
+ virtual void idleStarted() = 0;
+ virtual void idleFinished() = 0;
+
+ virtual std::unique_ptr<V8InspectorSession> connect(int contextGroupId) = 0;
+ virtual bool isPaused() = 0;
+
+ static v8::Local<v8::Private> scopeExtensionPrivate(v8::Isolate*);
+ static bool isCommandLineAPIMethod(const String16& name);
+ static bool isCommandLineAPIGetter(const String16& name);
+
+ virtual std::unique_ptr<V8StackTrace> createStackTrace(v8::Local<v8::StackTrace>, size_t maxStackSize) = 0;
+ virtual std::unique_ptr<V8StackTrace> captureStackTrace(size_t maxStackSize) = 0;
+};
+
+} // namespace blink
+
+
+#endif // V8Debugger_h
diff --git a/deps/v8_inspector/platform/v8_inspector/public/V8DebuggerAgent.h b/deps/v8_inspector/platform/v8_inspector/public/V8DebuggerAgent.h
new file mode 100644
index 0000000000..6a18e62fca
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/public/V8DebuggerAgent.h
@@ -0,0 +1,24 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8DebuggerAgent_h
+#define V8DebuggerAgent_h
+
+#include "platform/PlatformExport.h"
+#include "platform/inspector_protocol/Dispatcher.h"
+#include "platform/v8_inspector/public/V8Debugger.h"
+
+namespace blink {
+
+class V8RuntimeAgent;
+
+class PLATFORM_EXPORT V8DebuggerAgent : public protocol::Backend::Debugger, public V8Debugger::Agent<protocol::Frontend::Debugger> {
+public:
+ virtual ~V8DebuggerAgent() { }
+};
+
+} // namespace blink
+
+
+#endif // V8DebuggerAgent_h
diff --git a/deps/v8_inspector/platform/v8_inspector/public/V8DebuggerClient.h b/deps/v8_inspector/platform/v8_inspector/public/V8DebuggerClient.h
new file mode 100644
index 0000000000..29b041ce29
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/public/V8DebuggerClient.h
@@ -0,0 +1,54 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8DebuggerClient_h
+#define V8DebuggerClient_h
+
+#include "platform/PlatformExport.h"
+#include "platform/v8_inspector/public/ConsoleAPITypes.h"
+#include "platform/v8_inspector/public/ConsoleTypes.h"
+#include "platform/v8_inspector/public/V8ContextInfo.h"
+#include "platform/v8_inspector/public/V8EventListenerInfo.h"
+
+#include <v8.h>
+
+namespace blink {
+
+class PLATFORM_EXPORT V8DebuggerClient {
+public:
+ virtual ~V8DebuggerClient() { }
+ virtual void runMessageLoopOnPause(int contextGroupId) = 0;
+ virtual void quitMessageLoopOnPause() = 0;
+ virtual void muteWarningsAndDeprecations() = 0;
+ virtual void unmuteWarningsAndDeprecations() = 0;
+ virtual void muteConsole() = 0;
+ virtual void unmuteConsole() = 0;
+ virtual void beginUserGesture() = 0;
+ virtual void endUserGesture() = 0;
+ virtual void eventListeners(v8::Local<v8::Value>, V8EventListenerInfoList&) = 0;
+ virtual bool callingContextCanAccessContext(v8::Local<v8::Context> calling, v8::Local<v8::Context> target) = 0;
+ virtual String16 valueSubtype(v8::Local<v8::Value>) = 0;
+ virtual bool formatAccessorsAsProperties(v8::Local<v8::Value>) = 0;
+ virtual bool isExecutionAllowed() = 0;
+ virtual double currentTimeMS() = 0;
+ virtual int ensureDefaultContextInGroup(int contextGroupId) = 0;
+ virtual bool isInspectableHeapObject(v8::Local<v8::Object>) = 0;
+
+ virtual void reportMessageToConsole(v8::Local<v8::Context>, MessageType, MessageLevel, const String16& message, const v8::FunctionCallbackInfo<v8::Value>* arguments, unsigned skipArgumentCount, int maxStackSize) = 0;
+
+ virtual void consoleTime(const String16& title) = 0;
+ virtual void consoleTimeEnd(const String16& title) = 0;
+ virtual void consoleTimeStamp(const String16& title) = 0;
+
+ virtual v8::MaybeLocal<v8::Value> memoryInfo(v8::Isolate*, v8::Local<v8::Context>, v8::Local<v8::Object> creationContext) = 0;
+
+ typedef void (*TimerCallback)(void*);
+ virtual void startRepeatingTimer(double, TimerCallback, void* data) = 0;
+ virtual void cancelTimer(void* data) = 0;
+};
+
+} // namespace blink
+
+
+#endif // V8DebuggerClient_h
diff --git a/deps/v8_inspector/platform/v8_inspector/public/V8EventListenerInfo.h b/deps/v8_inspector/platform/v8_inspector/public/V8EventListenerInfo.h
new file mode 100644
index 0000000000..03370be8da
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/public/V8EventListenerInfo.h
@@ -0,0 +1,36 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8EventListenerInfo_h
+#define V8EventListenerInfo_h
+
+#include "platform/inspector_protocol/Collections.h"
+#include "platform/inspector_protocol/String16.h"
+
+#include <v8.h>
+
+namespace blink {
+
+class V8EventListenerInfo {
+public:
+ V8EventListenerInfo(const String16& eventType, bool useCapture, bool passive, v8::Local<v8::Object> handler)
+ : eventType(eventType)
+ , useCapture(useCapture)
+ , passive(passive)
+ , handler(handler)
+ {
+ }
+
+ const String16 eventType;
+ bool useCapture;
+ bool passive;
+ v8::Local<v8::Object> handler;
+
+};
+
+using V8EventListenerInfoList = protocol::Vector<V8EventListenerInfo>;
+
+} // namespace blink
+
+#endif // V8EventListenerInfo_h
diff --git a/deps/v8_inspector/platform/v8_inspector/public/V8HeapProfilerAgent.h b/deps/v8_inspector/platform/v8_inspector/public/V8HeapProfilerAgent.h
new file mode 100644
index 0000000000..ac3f522a3f
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/public/V8HeapProfilerAgent.h
@@ -0,0 +1,23 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8HeapProfilerAgent_h
+#define V8HeapProfilerAgent_h
+
+#include "platform/PlatformExport.h"
+#include "platform/inspector_protocol/Dispatcher.h"
+#include "platform/v8_inspector/public/V8Debugger.h"
+
+namespace blink {
+
+class V8RuntimeAgent;
+
+class PLATFORM_EXPORT V8HeapProfilerAgent : public protocol::Backend::HeapProfiler, public V8Debugger::Agent<protocol::Frontend::HeapProfiler> {
+public:
+ virtual ~V8HeapProfilerAgent() { }
+};
+
+} // namespace blink
+
+#endif // !defined(V8HeapProfilerAgent_h)
diff --git a/deps/v8_inspector/platform/v8_inspector/public/V8Inspector.cpp b/deps/v8_inspector/platform/v8_inspector/public/V8Inspector.cpp
new file mode 100644
index 0000000000..0ab85c7340
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/public/V8Inspector.cpp
@@ -0,0 +1,125 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+#include "platform/v8_inspector/public/V8Inspector.h"
+
+#include "platform/inspector_protocol/Dispatcher.h"
+#include "platform/v8_inspector/V8StringUtil.h"
+#include "platform/v8_inspector/public/V8Debugger.h"
+#include "platform/v8_inspector/public/V8DebuggerAgent.h"
+#include "platform/v8_inspector/public/V8DebuggerClient.h"
+#include "platform/v8_inspector/public/V8HeapProfilerAgent.h"
+#include "platform/v8_inspector/public/V8ProfilerAgent.h"
+#include "platform/v8_inspector/public/V8RuntimeAgent.h"
+
+namespace blink {
+
+V8Inspector::V8Inspector(v8::Isolate* isolate, v8::Local<v8::Context> context)
+{
+ m_debugger = V8Debugger::create(isolate, this);
+ m_session = m_debugger->connect(1);
+ m_session->setClient(this);
+ m_state = protocol::DictionaryValue::create();
+ m_state->setValue("runtime", protocol::DictionaryValue::create());
+ m_state->setValue("debugger", protocol::DictionaryValue::create());
+ m_state->setValue("profiler", protocol::DictionaryValue::create());
+ m_state->setValue("heapProfiler", protocol::DictionaryValue::create());
+
+ m_session->runtimeAgent()->setInspectorState(m_state->getObject("runtime"));
+ m_session->debuggerAgent()->setInspectorState(m_state->getObject("debugger"));
+ m_session->profilerAgent()->setInspectorState(m_state->getObject("profiler"));
+ m_session->heapProfilerAgent()->setInspectorState(m_state->getObject("heapProfiler"));
+
+ m_debugger->contextCreated(V8ContextInfo(context, 1, true, "",
+ "NodeJS Main Context", "", false));
+}
+
+V8Inspector::~V8Inspector()
+{
+ disconnectFrontend();
+}
+
+void V8Inspector::eventListeners(v8::Local<v8::Value> value, V8EventListenerInfoList& result)
+{
+}
+
+bool V8Inspector::callingContextCanAccessContext(v8::Local<v8::Context> calling, v8::Local<v8::Context> target)
+{
+ return true;
+}
+
+String16 V8Inspector::valueSubtype(v8::Local<v8::Value> value)
+{
+ return String16();
+}
+
+bool V8Inspector::formatAccessorsAsProperties(v8::Local<v8::Value> value)
+{
+ return false;
+}
+
+void V8Inspector::connectFrontend(protocol::FrontendChannel* channel)
+{
+ DCHECK(!m_frontend);
+ m_frontend = wrapUnique(new protocol::Frontend(channel));
+ m_dispatcher = protocol::Dispatcher::create(channel);
+
+ m_dispatcher->registerAgent((protocol::Backend::Debugger*)m_session->debuggerAgent());
+ m_dispatcher->registerAgent(m_session->heapProfilerAgent());
+ m_dispatcher->registerAgent(m_session->profilerAgent());
+ m_dispatcher->registerAgent(m_session->runtimeAgent());
+
+ m_session->debuggerAgent()->setFrontend(
+ protocol::Frontend::Debugger::from(m_frontend.get()));
+ m_session->heapProfilerAgent()->setFrontend(
+ protocol::Frontend::HeapProfiler::from(m_frontend.get()));
+ m_session->profilerAgent()->setFrontend(
+ protocol::Frontend::Profiler::from(m_frontend.get()));
+ m_session->runtimeAgent()->setFrontend(
+ protocol::Frontend::Runtime::from(m_frontend.get()));
+}
+
+void V8Inspector::disconnectFrontend()
+{
+ if (!m_frontend)
+ return;
+ m_dispatcher->clearFrontend();
+ m_dispatcher.reset();
+
+ m_session->debuggerAgent()->clearFrontend();
+ m_session->heapProfilerAgent()->clearFrontend();
+ m_session->profilerAgent()->clearFrontend();
+ m_session->runtimeAgent()->clearFrontend();
+
+ m_frontend.reset();
+}
+
+void V8Inspector::dispatchMessageFromFrontend(const String16& message)
+{
+ if (m_dispatcher)
+ m_dispatcher->dispatch(1, message);
+}
+
+int V8Inspector::ensureDefaultContextInGroup(int contextGroupId)
+{
+ return 1;
+}
+
+void V8Inspector::muteConsole()
+{
+
+}
+
+void V8Inspector::unmuteConsole()
+{
+
+}
+
+bool V8Inspector::isExecutionAllowed()
+{
+ return true;
+}
+
+} // namespace blink
diff --git a/deps/v8_inspector/platform/v8_inspector/public/V8Inspector.h b/deps/v8_inspector/platform/v8_inspector/public/V8Inspector.h
new file mode 100644
index 0000000000..33763014a8
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/public/V8Inspector.h
@@ -0,0 +1,81 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8Inspector_h
+#define V8Inspector_h
+
+#include "platform/v8_inspector/public/V8DebuggerClient.h"
+#include "platform/v8_inspector/public/V8InspectorSessionClient.h"
+#include "platform/v8_inspector/public/V8InspectorSession.h"
+
+#include "wtf/PtrUtil.h"
+#include <v8.h>
+
+namespace blink {
+
+namespace protocol {
+class Dispatcher;
+class Frontend;
+class FrontendChannel;
+}
+
+class V8Debugger;
+class V8HeapProfilerAgent;
+class V8ProfilerAgent;
+
+class V8Inspector : public V8DebuggerClient, V8InspectorSessionClient {
+public:
+ V8Inspector(v8::Isolate*, v8::Local<v8::Context>);
+ ~V8Inspector();
+
+ // Transport interface.
+ void connectFrontend(protocol::FrontendChannel*);
+ void disconnectFrontend();
+ void dispatchMessageFromFrontend(const String16& message);
+
+private:
+ void eventListeners(v8::Local<v8::Value>, V8EventListenerInfoList&) override;
+ bool callingContextCanAccessContext(v8::Local<v8::Context> calling, v8::Local<v8::Context> target) override;
+ String16 valueSubtype(v8::Local<v8::Value>) override;
+ bool formatAccessorsAsProperties(v8::Local<v8::Value>) override;
+ void muteWarningsAndDeprecations() override { }
+ void unmuteWarningsAndDeprecations() override { }
+ double currentTimeMS() override { return 0; };
+
+ void muteConsole() override;
+ void unmuteConsole() override;
+ bool isExecutionAllowed() override;
+ int ensureDefaultContextInGroup(int contextGroupId) override;
+ void beginUserGesture() override { }
+ void endUserGesture() override { }
+ bool isInspectableHeapObject(v8::Local<v8::Object>) override { return true; }
+ void consoleTime(const String16& title) override { }
+ void consoleTimeEnd(const String16& title) override { }
+ void consoleTimeStamp(const String16& title) override { }
+ v8::MaybeLocal<v8::Value> memoryInfo(v8::Isolate*, v8::Local<v8::Context>, v8::Local<v8::Object> creationContext) override
+ {
+ return v8::MaybeLocal<v8::Value>();
+ }
+ void reportMessageToConsole(v8::Local<v8::Context>, MessageType, MessageLevel, const String16& message, const v8::FunctionCallbackInfo<v8::Value>* arguments, unsigned skipArgumentCount, int maxStackSize) override { }
+
+ // V8InspectorSessionClient
+ void startInstrumenting() override { }
+ void stopInstrumenting() override { }
+ void resumeStartup() override { }
+ bool canExecuteScripts() override { return true; }
+ void profilingStarted() override { }
+ void profilingStopped() override { }
+ void startRepeatingTimer(double, TimerCallback, void* data) override { }
+ void cancelTimer(void* data) override { }
+
+ std::unique_ptr<V8Debugger> m_debugger;
+ std::unique_ptr<V8InspectorSession> m_session;
+ std::unique_ptr<protocol::Dispatcher> m_dispatcher;
+ std::unique_ptr<protocol::Frontend> m_frontend;
+ std::unique_ptr<protocol::DictionaryValue> m_state;
+};
+
+}
+
+#endif // V8Inspector_h
diff --git a/deps/v8_inspector/platform/v8_inspector/public/V8InspectorSession.h b/deps/v8_inspector/platform/v8_inspector/public/V8InspectorSession.h
new file mode 100644
index 0000000000..dfb9ff6386
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/public/V8InspectorSession.h
@@ -0,0 +1,67 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8InspectorSession_h
+#define V8InspectorSession_h
+
+#include "platform/PlatformExport.h"
+#include "platform/inspector_protocol/TypeBuilder.h"
+#include "wtf/PtrUtil.h"
+
+#include <v8.h>
+
+namespace blink {
+
+class V8DebuggerAgent;
+class V8HeapProfilerAgent;
+class V8InspectorSessionClient;
+class V8ProfilerAgent;
+class V8RuntimeAgent;
+
+class PLATFORM_EXPORT V8InspectorSession {
+public:
+ static const char backtraceObjectGroup[];
+
+ // Cross-context inspectable values (DOM nodes in different worlds, etc.).
+ class Inspectable {
+ public:
+ virtual v8::Local<v8::Value> get(v8::Local<v8::Context>) = 0;
+ virtual ~Inspectable() { }
+ };
+
+ virtual ~V8InspectorSession() { }
+
+ virtual void setClient(V8InspectorSessionClient*) = 0;
+ virtual void addInspectedObject(std::unique_ptr<Inspectable>) = 0;
+
+ // API for the embedder to report native activities.
+ virtual void schedulePauseOnNextStatement(const String16& breakReason, std::unique_ptr<protocol::DictionaryValue> data) = 0;
+ virtual void cancelPauseOnNextStatement() = 0;
+ virtual void breakProgram(const String16& breakReason, std::unique_ptr<protocol::DictionaryValue> data) = 0;
+ virtual void breakProgramOnException(const String16& breakReason, std::unique_ptr<protocol::DictionaryValue> data) = 0;
+ virtual void setSkipAllPauses(bool) = 0;
+
+ // API to report async call stacks.
+ virtual void asyncTaskScheduled(const String16& taskName, void* task, bool recurring) = 0;
+ virtual void asyncTaskCanceled(void* task) = 0;
+ virtual void asyncTaskStarted(void* task) = 0;
+ virtual void asyncTaskFinished(void* task) = 0;
+ virtual void allAsyncTasksCanceled() = 0;
+
+ // API to work with remote objects.
+ virtual std::unique_ptr<protocol::Runtime::RemoteObject> wrapObject(v8::Local<v8::Context>, v8::Local<v8::Value>, const String16& groupName, bool generatePreview = false) = 0;
+ // FIXME: remove when InspectorConsoleAgent moves into V8 inspector.
+ virtual std::unique_ptr<protocol::Runtime::RemoteObject> wrapTable(v8::Local<v8::Context>, v8::Local<v8::Value> table, v8::Local<v8::Value> columns) = 0;
+ virtual v8::Local<v8::Value> findObject(ErrorString*, const String16& objectId, v8::Local<v8::Context>* = nullptr, String16* objectGroup = nullptr) = 0;
+ virtual void releaseObjectGroup(const String16&) = 0;
+
+ virtual V8DebuggerAgent* debuggerAgent() = 0;
+ virtual V8HeapProfilerAgent* heapProfilerAgent() = 0;
+ virtual V8ProfilerAgent* profilerAgent() = 0;
+ virtual V8RuntimeAgent* runtimeAgent() = 0;
+};
+
+} // namespace blink
+
+#endif // V8InspectorSession_h
diff --git a/deps/v8_inspector/platform/v8_inspector/public/V8InspectorSessionClient.h b/deps/v8_inspector/platform/v8_inspector/public/V8InspectorSessionClient.h
new file mode 100644
index 0000000000..e4775ffc16
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/public/V8InspectorSessionClient.h
@@ -0,0 +1,28 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8InspectorSessionClient_h
+#define V8InspectorSessionClient_h
+
+#include "platform/PlatformExport.h"
+
+#include <v8.h>
+
+namespace blink {
+
+class PLATFORM_EXPORT V8InspectorSessionClient {
+public:
+ virtual ~V8InspectorSessionClient() { }
+ virtual void startInstrumenting() = 0;
+ virtual void stopInstrumenting() = 0;
+ virtual void resumeStartup() = 0;
+ virtual bool canExecuteScripts() = 0;
+ virtual void profilingStarted() = 0;
+ virtual void profilingStopped() = 0;
+};
+
+} // namespace blink
+
+
+#endif // V8InspectorSessionClient_h
diff --git a/deps/v8_inspector/platform/v8_inspector/public/V8ProfilerAgent.h b/deps/v8_inspector/platform/v8_inspector/public/V8ProfilerAgent.h
new file mode 100644
index 0000000000..dacf8a0bc3
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/public/V8ProfilerAgent.h
@@ -0,0 +1,22 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8ProfilerAgent_h
+#define V8ProfilerAgent_h
+
+#include "platform/PlatformExport.h"
+#include "platform/inspector_protocol/Dispatcher.h"
+#include "platform/v8_inspector/public/V8Debugger.h"
+
+namespace blink {
+
+class PLATFORM_EXPORT V8ProfilerAgent : public protocol::Backend::Profiler, public V8Debugger::Agent<protocol::Frontend::Profiler> {
+public:
+ virtual ~V8ProfilerAgent() { }
+};
+
+} // namespace blink
+
+
+#endif // !defined(V8ProfilerAgent_h)
diff --git a/deps/v8_inspector/platform/v8_inspector/public/V8RuntimeAgent.h b/deps/v8_inspector/platform/v8_inspector/public/V8RuntimeAgent.h
new file mode 100644
index 0000000000..917114f42b
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/public/V8RuntimeAgent.h
@@ -0,0 +1,23 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8RuntimeAgent_h
+#define V8RuntimeAgent_h
+
+#include "platform/PlatformExport.h"
+#include "platform/inspector_protocol/Dispatcher.h"
+#include "platform/v8_inspector/public/V8Debugger.h"
+
+namespace blink {
+
+class InjectedScriptManager;
+
+class PLATFORM_EXPORT V8RuntimeAgent : public protocol::Backend::Runtime, public V8Debugger::Agent<protocol::Frontend::Runtime> {
+public:
+ virtual ~V8RuntimeAgent() { }
+};
+
+} // namespace blink
+
+#endif // V8RuntimeAgent_h
diff --git a/deps/v8_inspector/platform/v8_inspector/public/V8StackTrace.h b/deps/v8_inspector/platform/v8_inspector/public/V8StackTrace.h
new file mode 100644
index 0000000000..da716c99bf
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/public/V8StackTrace.h
@@ -0,0 +1,42 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8StackTrace_h
+#define V8StackTrace_h
+
+#include "platform/inspector_protocol/TypeBuilder.h"
+#include "wtf/PtrUtil.h"
+
+#include <v8.h>
+
+namespace blink {
+
+class TracedValue;
+
+const v8::StackTrace::StackTraceOptions stackTraceOptions = static_cast<v8::StackTrace::StackTraceOptions>(
+ v8::StackTrace::kLineNumber |
+ v8::StackTrace::kColumnOffset |
+ v8::StackTrace::kScriptId |
+ v8::StackTrace::kScriptNameOrSourceURL |
+ v8::StackTrace::kFunctionName);
+
+class V8StackTrace {
+public:
+ static const size_t maxCallStackSizeToCapture = 200;
+
+ virtual bool isEmpty() const = 0;
+ virtual String16 topSourceURL() const = 0;
+ virtual int topLineNumber() const = 0;
+ virtual int topColumnNumber() const = 0;
+ virtual String16 topScriptId() const = 0;
+ virtual String16 topFunctionName() const = 0;
+
+ virtual ~V8StackTrace() { }
+ virtual std::unique_ptr<protocol::Runtime::StackTrace> buildInspectorObject() const = 0;
+ virtual String16 toString() const = 0;
+};
+
+} // namespace blink
+
+#endif // V8StackTrace_h
diff --git a/deps/v8_inspector/platform/v8_inspector/public/V8ToProtocolValue.h b/deps/v8_inspector/platform/v8_inspector/public/V8ToProtocolValue.h
new file mode 100644
index 0000000000..c3c692f995
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/public/V8ToProtocolValue.h
@@ -0,0 +1,17 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8ToProtocolValue_h
+#define V8ToProtocolValue_h
+
+#include "platform/inspector_protocol/Values.h"
+#include <v8.h>
+
+namespace blink {
+
+PLATFORM_EXPORT std::unique_ptr<protocol::Value> toProtocolValue(v8::Local<v8::Context>, v8::Local<v8::Value>, int maxDepth = protocol::Value::maxDepth);
+
+} // namespace blink
+
+#endif // V8ToProtocolValue_h
diff --git a/deps/v8_inspector/platform/v8_inspector/v8_inspector.gyp b/deps/v8_inspector/platform/v8_inspector/v8_inspector.gyp
new file mode 100644
index 0000000000..20df5e8bc3
--- /dev/null
+++ b/deps/v8_inspector/platform/v8_inspector/v8_inspector.gyp
@@ -0,0 +1,48 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ # GN version: //third_party/WebKit/Source/platform:inspector_injected_script
+ 'target_name': 'inspector_injected_script',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'action_name': 'ConvertFileToHeaderWithCharacterArray',
+ 'inputs': [
+ 'build/xxd.py',
+ 'InjectedScriptSource.js',
+ ],
+ 'outputs': [ '<(SHARED_INTERMEDIATE_DIR)/blink/platform/v8_inspector/InjectedScriptSource.h', ],
+ 'action': [
+ 'python', 'build/xxd.py', 'InjectedScriptSource_js', 'InjectedScriptSource.js', '<@(_outputs)'
+ ],
+ },
+ ],
+ # Since this target generates header files, it needs to be a hard dependency.
+ 'hard_dependency': 1,
+ },
+ {
+ # GN version: //third_party/WebKit/Source/platform:inspector_debugger_script
+ 'target_name': 'inspector_debugger_script',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'action_name': 'ConvertFileToHeaderWithCharacterArray',
+ 'inputs': [
+ 'build/xxd.py',
+ 'DebuggerScript.js',
+ ],
+ 'outputs': [ '<(SHARED_INTERMEDIATE_DIR)/blink/platform/v8_inspector/DebuggerScript.h', ],
+ 'action': [
+ 'python', 'build/xxd.py', 'DebuggerScript_js', 'DebuggerScript.js', '<@(_outputs)'
+ ],
+ },
+ ],
+ # Since this target generates header files, it needs to be a hard dependency.
+ 'hard_dependency': 1,
+ },
+ ], # targets
+}
diff --git a/deps/v8_inspector/v8_inspector.gyp b/deps/v8_inspector/v8_inspector.gyp
new file mode 100644
index 0000000000..59d8843b8e
--- /dev/null
+++ b/deps/v8_inspector/v8_inspector.gyp
@@ -0,0 +1,35 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'includes': [
+ 'v8_inspector.gypi',
+ ],
+
+ 'targets': [
+ {
+ 'target_name': 'v8_inspector',
+ 'type': '<(component)',
+
+ 'dependencies': [
+ 'platform/inspector_protocol/protocol.gyp:protocol_sources',
+ 'platform/v8_inspector/v8_inspector.gyp:inspector_injected_script',
+ 'platform/v8_inspector/v8_inspector.gyp:inspector_debugger_script',
+ ],
+ 'defines': [
+ 'V8_INSPECTOR_USE_STL=1'
+ ],
+ 'include_dirs': [
+ '.',
+ 'deps/wtf',
+ '../v8/include',
+ '../v8',
+ '<(SHARED_INTERMEDIATE_DIR)/blink',
+ ],
+ 'sources': [
+ '<@(v8_inspector_files)',
+ ],
+ },
+ ] # end targets
+}
diff --git a/deps/v8_inspector/v8_inspector.gypi b/deps/v8_inspector/v8_inspector.gypi
new file mode 100644
index 0000000000..aad781b684
--- /dev/null
+++ b/deps/v8_inspector/v8_inspector.gypi
@@ -0,0 +1,94 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'v8_inspector_files': [
+
+ '<(SHARED_INTERMEDIATE_DIR)/blink/platform/inspector_protocol/Backend.h',
+ '<(SHARED_INTERMEDIATE_DIR)/blink/platform/inspector_protocol/Dispatcher.cpp',
+ '<(SHARED_INTERMEDIATE_DIR)/blink/platform/inspector_protocol/Dispatcher.h',
+ '<(SHARED_INTERMEDIATE_DIR)/blink/platform/inspector_protocol/Frontend.cpp',
+ '<(SHARED_INTERMEDIATE_DIR)/blink/platform/inspector_protocol/Frontend.h',
+ '<(SHARED_INTERMEDIATE_DIR)/blink/platform/inspector_protocol/TypeBuilder.cpp',
+ '<(SHARED_INTERMEDIATE_DIR)/blink/platform/inspector_protocol/TypeBuilder.h',
+ 'platform/v8_inspector/public/V8Inspector.cpp',
+ 'platform/v8_inspector/public/V8Inspector.h',
+
+ 'platform/inspector_protocol/Allocator.h',
+ 'platform/inspector_protocol/Array.h',
+ 'platform/inspector_protocol/Collections.h',
+ 'platform/inspector_protocol/CollectionsSTL.h',
+ 'platform/inspector_protocol/ErrorSupport.cpp',
+ 'platform/inspector_protocol/ErrorSupport.h',
+ 'platform/inspector_protocol/Maybe.h',
+ 'platform/inspector_protocol/Parser.cpp',
+ 'platform/inspector_protocol/Parser.h',
+ 'platform/inspector_protocol/FrontendChannel.h',
+ 'platform/inspector_protocol/String16.h',
+ 'platform/inspector_protocol/String16STL.cpp',
+ 'platform/inspector_protocol/String16STL.h',
+ 'platform/inspector_protocol/Values.cpp',
+ 'platform/inspector_protocol/Values.h',
+ 'platform/inspector_protocol/ValueConversions.cpp',
+ 'platform/inspector_protocol/ValueConversions.h',
+ 'platform/v8_inspector/Atomics.h',
+ 'platform/v8_inspector/InspectorWrapper.cpp',
+ 'platform/v8_inspector/InspectorWrapper.h',
+ 'platform/v8_inspector/IgnoreExceptionsScope.h',
+ 'platform/v8_inspector/InjectedScript.cpp',
+ 'platform/v8_inspector/InjectedScript.h',
+ 'platform/v8_inspector/InjectedScriptNative.cpp',
+ 'platform/v8_inspector/InjectedScriptNative.h',
+ 'platform/v8_inspector/InspectedContext.cpp',
+ 'platform/v8_inspector/InspectedContext.h',
+ 'platform/v8_inspector/JavaScriptCallFrame.cpp',
+ 'platform/v8_inspector/JavaScriptCallFrame.h',
+ 'platform/v8_inspector/MuteConsoleScope.h',
+ 'platform/v8_inspector/ScriptBreakpoint.h',
+ 'platform/v8_inspector/RemoteObjectId.cpp',
+ 'platform/v8_inspector/RemoteObjectId.h',
+ 'platform/v8_inspector/V8Console.cpp',
+ 'platform/v8_inspector/V8Console.h',
+ 'platform/v8_inspector/V8DebuggerAgentImpl.cpp',
+ 'platform/v8_inspector/V8DebuggerAgentImpl.h',
+ 'platform/v8_inspector/V8DebuggerImpl.cpp',
+ 'platform/v8_inspector/V8DebuggerImpl.h',
+ 'platform/v8_inspector/V8DebuggerScript.cpp',
+ 'platform/v8_inspector/V8DebuggerScript.h',
+ 'platform/v8_inspector/V8FunctionCall.cpp',
+ 'platform/v8_inspector/V8FunctionCall.h',
+ 'platform/v8_inspector/V8HeapProfilerAgentImpl.cpp',
+ 'platform/v8_inspector/V8HeapProfilerAgentImpl.h',
+ 'platform/v8_inspector/V8InjectedScriptHost.cpp',
+ 'platform/v8_inspector/V8InjectedScriptHost.h',
+ 'platform/v8_inspector/V8InspectorSessionImpl.cpp',
+ 'platform/v8_inspector/V8InspectorSessionImpl.h',
+ 'platform/v8_inspector/V8ProfilerAgentImpl.cpp',
+ 'platform/v8_inspector/V8ProfilerAgentImpl.h',
+ 'platform/v8_inspector/V8Regex.cpp',
+ 'platform/v8_inspector/V8Regex.h',
+ 'platform/v8_inspector/V8RuntimeAgentImpl.cpp',
+ 'platform/v8_inspector/V8RuntimeAgentImpl.h',
+ 'platform/v8_inspector/V8StackTraceImpl.cpp',
+ 'platform/v8_inspector/V8StackTraceImpl.h',
+ 'platform/v8_inspector/V8StringUtil.cpp',
+ 'platform/v8_inspector/V8StringUtil.h',
+ 'platform/v8_inspector/public/V8EventListenerInfo.h',
+ 'platform/v8_inspector/public/V8ContentSearchUtil.h',
+ 'platform/v8_inspector/public/V8ContextInfo.h',
+ 'platform/v8_inspector/public/V8Debugger.h',
+ 'platform/v8_inspector/public/V8DebuggerAgent.h',
+ 'platform/v8_inspector/public/V8DebuggerClient.h',
+ 'platform/v8_inspector/public/V8HeapProfilerAgent.h',
+ 'platform/v8_inspector/public/V8InspectorSession.h',
+ 'platform/v8_inspector/public/V8ProfilerAgent.h',
+ 'platform/v8_inspector/public/V8RuntimeAgent.h',
+ 'platform/v8_inspector/public/V8StackTrace.h',
+ 'platform/v8_inspector/public/V8ToProtocolValue.h',
+ '<(SHARED_INTERMEDIATE_DIR)/blink/platform/v8_inspector/DebuggerScript.h',
+ '<(SHARED_INTERMEDIATE_DIR)/blink/platform/v8_inspector/InjectedScriptSource.h',
+ ],
+ }
+}