diff --git a/OAT.xml b/OAT.xml
index 4b367e99e643623db481d37410d810620a587119..daadca047a5d8ede81f09a65e8edb7f116ad80be 100644
--- a/OAT.xml
+++ b/OAT.xml
@@ -60,6 +60,7 @@ Note:If the text contains special characters, please escape them according to th
+
diff --git a/arkguard/.gitignore b/arkguard/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..c18ed016a7f867069687a82a35d5d592f56c6d30
--- /dev/null
+++ b/arkguard/.gitignore
@@ -0,0 +1,2 @@
+node_modules/
+lib/
\ No newline at end of file
diff --git a/arkguard/.vscode/launch.json b/arkguard/.vscode/launch.json
new file mode 100644
index 0000000000000000000000000000000000000000..d365f5d3677a1ce5983754bd4880017617962ce4
--- /dev/null
+++ b/arkguard/.vscode/launch.json
@@ -0,0 +1,35 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "type": "node",
+ "request": "launch",
+ "name": "Arkguard Debug",
+ "program": "--loader=ts-node/esm",
+ "args": [
+ "./src/cli/SecHarmony.ts",
+ "${workspaceFolder}/test/test.ts",
+ "--config-path",
+ "${workspaceFolder}/test/config.json"
+ ],
+ "sourceMaps": true,
+ "smartStep": true,
+ "console": "integratedTerminal",
+ "stopOnEntry": true
+ },
+
+ {
+ "type": "node",
+ "request": "launch",
+ "name": "Launch Program",
+ "skipFiles": [
+ "/**"
+ ],
+ "program": "${workspaceFolder}/lib/ArkObfuscator.js",
+ "preLaunchTask": "tsc: build - tsconfig.json",
+ "outFiles": [
+ "${workspaceFolder}/lib/**/*.js"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/arkguard/LICENSE b/arkguard/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..563750d672e448ef552ceffafa4c43d197493f1b
--- /dev/null
+++ b/arkguard/LICENSE
@@ -0,0 +1,196 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ The "ts2panda\scripts\diagnosticMessages.json" file may contain
+ some information or content from the following software:
+ TypeScript
+ /*! *****************************************************************************
+ Copyright (c) Microsoft Corporation. All rights reserved.
+ 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
+
+ THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
+ WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
+ MERCHANTABLITY OR NON-INFRINGEMENT.
+
+ See the Apache Version 2.0 License for specific language governing permissions
+ and limitations under the License.
+ ***************************************************************************** */
+ Apache License 2.0
\ No newline at end of file
diff --git a/arkguard/OAT.xml b/arkguard/OAT.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e51df6495fd4c51b3a18868e6d7ba0f3f3522818
--- /dev/null
+++ b/arkguard/OAT.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/arkguard/README.md b/arkguard/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..ebf73869dbd9e06c60fc0abfca7ab9663ea752c9
--- /dev/null
+++ b/arkguard/README.md
@@ -0,0 +1,236 @@
+# Arkguard
+Arkguard is a javascript and typescript obfuscation tool.
+
+# Usage in DevEco Studio
+Arkguard has been integrated into SDK. It is convenient to use Arkguard in DevEco Studio.
+In DevEco Studio, Arkguard can be enabled only in Stage Model (FA Model is not supported).
+For now only name obfuscations can be used in DevEco Studio (because other obfuscation
+abilities of Arkguard may hurt execution performance).
+You can obfuscate the following names:
+* parameter names and local variable names
+* names in global scope
+* property names
+
+We enable the obfuscation of parameter names and local variable names by default. However,
+global names obfuscation and property names obfuscation are disabled by default, as they may
+cause runtime error if they are enabled by default.
+You can enable them by [obfuscation options](#obfuscation-options).
+
+When you create a new project, the following config will be generated in `build-profile.json5`.
+```
+"buildOption": {
+ "arkOptions": {
+ "obfuscation": {
+ "ruleOptions": {
+ "enable": true,
+ "rules": ["obfusation-rules.txt"],
+ }
+ }
+ }
+}
+```
+When you create a new library, additional property `consumerRules` will be added.
+```
+"buildOption": {
+ "arkOptions": {
+ "obfuscation": {
+ "ruleOptions": {
+ "enable": true,
+ "rules": ["obfusation-rules.txt"],
+ }
+ "consumerRules": ["consumer-rules.txt"]
+ }
+ }
+}
+```
+
+To enable obfuscation, the following conditions should be satisfied:
+* the property `ruleOptions.enable` is `true` and the property `ruleOptions.enable` of every dependency library is `true`.
+* build in release mode
+
+The rules in the property `ruleOptions.rules` will be applied when you build HAP or HAR.
+
+The rules in the property `consumerRules` will be applied when you build the project or library which
+depends on this library. They will also be merged into a file `obfuscation.txt` in the resulting HAR.
+
+When you are building HAP or HAR, the final obfucation rules are combination of self's `ruleOptions.rules`
+property, dependency libraries' `consumerRules` properties and dependency HAR's `obfuscation.txt`.
+If your building HAR, the content of `obfuscation.txt` are the combination of self's `consumerRules` property,
+dependency libraries' `consumerRules` properties and dependency HAR's `obfuscation.txt`. If you are building
+HAP, `obfuscation.txt` will not be generated.
+
+## Write rules
+
+The files `obfusation-rules.txt` and `consumer-rules.txt` are created by DevEco Studio automatically, but they do not
+contain any rule by default. You can write rules in these files or include rules from other files, as the following
+example shows.
+```
+"buildOption": {
+ "arkOptions": {
+ "obfuscation": {
+ "ruleOptions": {
+ "enable": true,
+ "rules": ["obfusation-rules.txt", "myrules.txt"],
+ }
+ "consumerRules": ["consumer-rules.txt", "my-consumer-rules.txt"]
+ }
+ }
+}
+```
+
+In rule files, you can write [obfuscation options](#obfuscation-options) and [keep options](#keep-options).
+
+### Obfuscation options
+
+`-disable-obfusation`
+
+Specifies to disable all obfuscations. If you use this option, the resulting HAP or HAR will not be obfuscated. By default,
+Arkguard only obfuscates the parameter names and local variable names by assigning random short names to them.
+
+`-enable-property-obfuscation`
+
+Specifies to obfuscate the property names. If you use this option, all property names will be obfuscated except the
+following:
+* the property names of `import/export` classes or objects.
+* the property names defined in UI components. For example, the property names `message` and `data` in
+ ```
+ @Component struct MyExample {
+ @State message: string = "hello";
+ data: number[] = [];
+ ...
+ }
+ ```
+ will not be obfuscated.
+* the property names that are specified by [keep options](#keep-options).
+* the property names in system API list. System API list is a name set which is extracted from SDK automatically by default.
+
+`-enable-toplevel-obfuscation`
+
+Specifies to obfuscate the names in the global scope. If you use this option, all global names will be obfuscated
+except the following:
+* the `import/export` global names.
+* the global names that are not declared in the current file.
+* the global names that are specified by [keep options](#keep-options).
+* the global names in system API list.
+
+`-compact`
+
+Specifies to remove unnecessary blank spaces and all line feeds. If you use this option, all code will be compressed into
+one line.
+
+`-remove-log`
+
+Specifies to remove all `console.*` statements.
+
+`-print-namecache` filepath
+
+Specifies to print the name cache that contains the mapping from the old names to new names. The cache will printed to
+the given file. If you use `-enable-property-obfuscation` or `-enable-toplevel-obfuscation`, and you want incremental
+obfuscation in the future (for example, hot fix), then you should use this option and keep the resulting cache file
+carefully.
+
+`-apply-namecache` filepath
+
+Specifies to reuse the given cache file. The old names in the cache will receive the corresponding new names specified in
+the cache. Other names will receive new random short names. This option should be used in incremental obfuscation.
+
+By default, DevEco Studio will keep and update the namecache file in the temporary cache directory and apply the cache for
+incremental compilation.
+
+### Keep options
+
+Keep options are useful only when you use `enable-property-obfuscation` or `enable-toplevel-obfuscation`.
+
+`-keep-property-name` [,modifiers,...]
+
+Specifies property names that you want to keep. For example,
+```
+-keep-property-name
+age
+firstName
+lastName
+```
+
+**What property names should be kept?**
+
+Property obfuscation will not obfuscate the string literals and properties that are accessed dynamically.
+So for safety, we would suggest keeping all property names that are accessed dynamically.
+
+Example:
+```
+var obj = {x0: 0, x1: 0, x2: 0};
+for (var i = 0; i < 2; i++) {
+ console.log(obj['x' + i]); // x0, x1, x2 should be kept
+}
+
+Object.defineProperty(obj, 'y', {});
+console.log(obj.y); // y should be kept
+
+obj.s = 0;
+let key = 's';
+console.log(obj[key]); // s should be kept
+
+obj.u = 0;
+console.log(obj.u); // u can be safely obfuscated
+
+obj.t = 0;
+console.log(obj['t']); // t and 't' can be safely obfuscated, but we suggest keeping t
+
+obj.['v'] = 0;
+console.log(obj['v']); // 'v' can be safely obfuscated, but we suggest keeping v
+```
+
+`-keep-global-name` [,modifiers,...]
+
+Specifies names that you want to keep in the global scope. For example,
+```
+-keep-global-name
+Person
+printPersonName
+```
+
+**What global names should be kept?**
+
+It is known that in javascript the variables in the global scope are properties of `globalThis`. So if in your code
+you access a global variable as a property, then the global name should be kept.
+
+Example:
+```
+var a = 0;
+console.log(globalThis.a); // a should be kept
+
+function foo(){}
+globalThis.foo(); // foo should be kept
+
+var c = 0;
+console.log(c); // c can be safely obfuscated
+
+function bar(){}
+bar(); // bar can be safely obfuscated
+
+class MyClass {}
+let d = new MyClass(); // MyClass can be safely obfuscated
+```
+
+`-keep-dts` filepath
+
+Specifies to keep names in the given `.d.ts` file. Here filepath can be also a directory. If so, then the names in all
+`d.ts` files under the given directory will be kept.
+If your are building HAR with this option, then the kept names will be merged into the resulting `obfuscation.txt`.
+
+### Comments
+
+You can write comments in rules file by using `#`. For each line, the content beginning with `#` and ending with the
+line feed will be treated as comment. For example,
+```
+# white list for MainAbility.ets
+-keep-global-name
+MyComponent
+GlobalFunction
+
+-keep-property-name # white list for dynamic property names
+firstName
+lastName
+age
+```
+If your are building HAR, comments will not be merged into the resulting `obfuscation.txt`.
\ No newline at end of file
diff --git a/arkguard/bin/secharmony b/arkguard/bin/secharmony
new file mode 100644
index 0000000000000000000000000000000000000000..ad2d3a2587cad7a9a03354f1a753749526f14a10
--- /dev/null
+++ b/arkguard/bin/secharmony
@@ -0,0 +1,18 @@
+#!/usr/bin/env node
+
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+require("../lib/cli/SecHarmony.js");
\ No newline at end of file
diff --git a/arkguard/build_package/arkguard-1.0.0.tgz b/arkguard/build_package/arkguard-1.0.0.tgz
new file mode 100644
index 0000000000000000000000000000000000000000..d23c627d5838f5c1ebe6885b8a9c43f8beccc6bf
Binary files /dev/null and b/arkguard/build_package/arkguard-1.0.0.tgz differ
diff --git a/arkguard/package-lock.json b/arkguard/package-lock.json
new file mode 100644
index 0000000000000000000000000000000000000000..d01c500b16a836374da1b78c16f7cf97412ffc7e
--- /dev/null
+++ b/arkguard/package-lock.json
@@ -0,0 +1,1184 @@
+{
+ "name": "arkguard",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "arkguard",
+ "version": "1.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "@ampproject/remapping": "2.2.0",
+ "commander": "^9.3.0",
+ "fs-extra": "^10.1.0"
+ },
+ "bin": {
+ "arkguard": "bin/secharmony"
+ },
+ "devDependencies": {
+ "@types/chai": "^4.3.1",
+ "@types/commander": "^2.12.2",
+ "@types/fs-extra": "^9.0.13",
+ "@types/mocha": "^9.1.1",
+ "@types/node": "^17.0.45",
+ "chai": "^4.3.6",
+ "mocha": "^10.0.0",
+ "ts-node": "^10.9.1"
+ }
+ },
+ "node_modules/@ampproject/remapping": {
+ "version": "2.2.0",
+ "resolved": "https://repo.huaweicloud.com/repository/npm/@ampproject/remapping/-/remapping-2.2.0.tgz",
+ "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.1.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@cspotcode/source-map-support": {
+ "version": "0.8.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "0.3.9"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.1.1",
+ "resolved": "https://repo.huaweicloud.com/repository/npm/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
+ "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/set-array": "^1.0.0",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.1.2",
+ "resolved": "https://repo.huaweicloud.com/repository/npm/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+ "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.15",
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.9",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "node_modules/@tsconfig/node10": {
+ "version": "1.0.9",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@tsconfig/node12": {
+ "version": "1.0.11",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@tsconfig/node14": {
+ "version": "1.0.3",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@tsconfig/node16": {
+ "version": "1.0.4",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/chai": {
+ "version": "4.3.5",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/commander": {
+ "version": "2.12.2",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "commander": "*"
+ }
+ },
+ "node_modules/@types/fs-extra": {
+ "version": "9.0.13",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/mocha": {
+ "version": "9.1.1",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "17.0.45",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/acorn": {
+ "version": "8.8.2",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-walk": {
+ "version": "8.2.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/ansi-colors": {
+ "version": "4.1.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/arg": {
+ "version": "4.1.3",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/assertion-error": {
+ "version": "1.1.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.2.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browser-stdout": {
+ "version": "1.3.1",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/camelcase": {
+ "version": "6.3.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/chai": {
+ "version": "4.3.7",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "assertion-error": "^1.1.0",
+ "check-error": "^1.0.2",
+ "deep-eql": "^4.1.2",
+ "get-func-name": "^2.0.0",
+ "loupe": "^2.3.1",
+ "pathval": "^1.1.1",
+ "type-detect": "^4.0.5"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chalk/node_modules/supports-color": {
+ "version": "7.2.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/check-error": {
+ "version": "1.0.2",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.5.3",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "7.0.4",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/commander": {
+ "version": "9.5.0",
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || >=14"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/create-require": {
+ "version": "1.1.1",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/debug/node_modules/ms": {
+ "version": "2.1.2",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/decamelize": {
+ "version": "4.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/deep-eql": {
+ "version": "4.1.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "type-detect": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/diff": {
+ "version": "5.0.0",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/escalade": {
+ "version": "3.1.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat": {
+ "version": "5.0.2",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "bin": {
+ "flat": "cli.js"
+ }
+ },
+ "node_modules/fs-extra": {
+ "version": "10.1.0",
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-func-name": {
+ "version": "2.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.0",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/glob/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/glob/node_modules/minimatch": {
+ "version": "3.1.2",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "license": "ISC"
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/he": {
+ "version": "1.2.0",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "he": "bin/he"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "2.1.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsonfile": {
+ "version": "6.1.0",
+ "license": "MIT",
+ "dependencies": {
+ "universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-symbols": {
+ "version": "4.1.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/loupe": {
+ "version": "2.3.6",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "get-func-name": "^2.0.0"
+ }
+ },
+ "node_modules/make-error": {
+ "version": "1.3.6",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/minimatch": {
+ "version": "5.0.1",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/mocha": {
+ "version": "10.2.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-colors": "4.1.1",
+ "browser-stdout": "1.3.1",
+ "chokidar": "3.5.3",
+ "debug": "4.3.4",
+ "diff": "5.0.0",
+ "escape-string-regexp": "4.0.0",
+ "find-up": "5.0.0",
+ "glob": "7.2.0",
+ "he": "1.2.0",
+ "js-yaml": "4.1.0",
+ "log-symbols": "4.1.0",
+ "minimatch": "5.0.1",
+ "ms": "2.1.3",
+ "nanoid": "3.3.3",
+ "serialize-javascript": "6.0.0",
+ "strip-json-comments": "3.1.1",
+ "supports-color": "8.1.1",
+ "workerpool": "6.2.1",
+ "yargs": "16.2.0",
+ "yargs-parser": "20.2.4",
+ "yargs-unparser": "2.0.0"
+ },
+ "bin": {
+ "_mocha": "bin/_mocha",
+ "mocha": "bin/mocha.js"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mochajs"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.3",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/pathval": {
+ "version": "1.1.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/randombytes": {
+ "version": "2.1.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/serialize-javascript": {
+ "version": "6.0.0",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "randombytes": "^2.1.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "8.1.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/ts-node": {
+ "version": "10.9.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@cspotcode/source-map-support": "^0.8.0",
+ "@tsconfig/node10": "^1.0.7",
+ "@tsconfig/node12": "^1.0.7",
+ "@tsconfig/node14": "^1.0.0",
+ "@tsconfig/node16": "^1.0.2",
+ "acorn": "^8.4.1",
+ "acorn-walk": "^8.1.1",
+ "arg": "^4.1.0",
+ "create-require": "^1.1.0",
+ "diff": "^4.0.1",
+ "make-error": "^1.1.1",
+ "v8-compile-cache-lib": "^3.0.1",
+ "yn": "3.1.1"
+ },
+ "bin": {
+ "ts-node": "dist/bin.js",
+ "ts-node-cwd": "dist/bin-cwd.js",
+ "ts-node-esm": "dist/bin-esm.js",
+ "ts-node-script": "dist/bin-script.js",
+ "ts-node-transpile-only": "dist/bin-transpile.js",
+ "ts-script": "dist/bin-script-deprecated.js"
+ },
+ "peerDependencies": {
+ "@swc/core": ">=1.2.50",
+ "@swc/wasm": ">=1.2.50",
+ "@types/node": "*",
+ "typescript": ">=2.7"
+ },
+ "peerDependenciesMeta": {
+ "@swc/core": {
+ "optional": true
+ },
+ "@swc/wasm": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ts-node/node_modules/diff": {
+ "version": "4.0.2",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/type-detect": {
+ "version": "4.0.8",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.0.4",
+ "resolved": "https://repo.huaweicloud.com/repository/npm/typescript/-/typescript-5.0.4.tgz",
+ "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "peer": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=12.20"
+ }
+ },
+ "node_modules/universalify": {
+ "version": "2.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/v8-compile-cache-lib": {
+ "version": "3.0.1",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/workerpool": {
+ "version": "6.2.1",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs": {
+ "version": "16.2.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^7.0.2",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.0",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^20.2.2"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "20.2.4",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs-unparser": {
+ "version": "2.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "camelcase": "^6.0.0",
+ "decamelize": "^4.0.0",
+ "flat": "^5.0.2",
+ "is-plain-obj": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yn": {
+ "version": "3.1.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ }
+}
diff --git a/arkguard/package.json b/arkguard/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..5b3496dd120f0f2ccc6ddf0220a39f059bcf5aa7
--- /dev/null
+++ b/arkguard/package.json
@@ -0,0 +1,51 @@
+{
+ "name": "arkguard",
+ "version": "1.0.0",
+ "description": "An obfuscator tools for open harmony apps.",
+ "bin": {
+ "arkguard": "bin/secharmony"
+ },
+ "main": "lib/ArkObfuscator.js",
+ "types": "lib/ArkObfuscator.d.ts",
+ "scripts": {
+ "clean": "rm -rf lib/*",
+ "build": "npm run clean && node node_modules/typescript/lib/tsc.js",
+ "test": "npm run test:ut && npm run test:grammar",
+ "test:ut": "node ./node_modules/mocha/bin/mocha --require ts-node/register ./test/ut/**/*.ts",
+ "test:grammar": "node --loader=ts-node/esm ./src/cli/SecHarmony.ts ./test/grammar --config-path ./scripts/grammarTestConfig.json && node ./scripts/grammarTestScript.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://codehub-dg-y.huawei.com/Jotun/secDroid/SecHarmony.git"
+ },
+ "keywords": [
+ "obfuscator",
+ "javascript",
+ "typescript"
+ ],
+ "author": "",
+ "license": "ISC",
+ "devDependencies": {
+ "@types/chai": "^4.3.1",
+ "@types/commander": "^2.12.2",
+ "@types/fs-extra": "^9.0.13",
+ "@types/mocha": "^9.1.1",
+ "@types/node": "^17.0.45",
+ "chai": "^4.3.6",
+ "mocha": "^10.0.0",
+ "ts-node": "^10.9.1"
+ },
+ "dependencies": {
+ "commander": "^9.3.0",
+ "fs-extra": "^10.1.0",
+ "source-map":"0.7.4"
+ },
+ "files": [
+ "bin",
+ "lib",
+ "package.json",
+ "tsconfig.base.json",
+ "tsconfig.json",
+ "README.md"
+ ]
+}
diff --git a/arkguard/scripts/grammarTestConfig.json b/arkguard/scripts/grammarTestConfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..ae6aa84637b7132fdcfc7424a846003eec9cba50
--- /dev/null
+++ b/arkguard/scripts/grammarTestConfig.json
@@ -0,0 +1,16 @@
+{
+ "mCompact": false,
+ "mRemoveComments": true,
+ "mOutputDir": "../test/local/",
+ "mDisableHilog": true,
+ "mDisableConsole":true,
+ "mNameObfuscation": {
+ "mEnable": true,
+ "mNameGeneratorType": 1,
+ "mRenameProperties": true,
+ "mReservedNames": []
+ },
+ "mEnableSourceMap": true,
+ "mEnableNameCache": false,
+ "mTopLevel":true
+}
\ No newline at end of file
diff --git a/arkguard/scripts/grammarTestScript.js b/arkguard/scripts/grammarTestScript.js
new file mode 100644
index 0000000000000000000000000000000000000000..9a416b5b74339316f79ae3876eafc18527f28269
--- /dev/null
+++ b/arkguard/scripts/grammarTestScript.js
@@ -0,0 +1,51 @@
+const fs = require('fs');
+const path = require('path');
+const { execSync } = require('child_process');
+
+const testDirectory = path.resolve('./test/local');
+
+function runTest(filePath) {
+ try {
+ const command = `node ./node_modules/ts-node/dist/bin.js ${filePath}`;
+ execSync(command);
+ return true;
+ } catch (error) {
+ console.error(`Test case ${filePath} failed:`, error);
+ return false;
+ }
+}
+let successCount = 0;
+let failureCount = 0;
+const failedFiles = [];
+
+function runTestsInDirectory(directoryPath) {
+ const files = fs.readdirSync(directoryPath);
+
+ for (const file of files) {
+ const filePath = path.join(directoryPath, file);
+
+ if (fs.statSync(filePath).isDirectory()) {
+ runTestsInDirectory(filePath);
+ } else if (path.extname(filePath) === '.ts') {
+ const isSuccess = runTest(filePath);
+ if (isSuccess) {
+ successCount++;
+ } else {
+ failureCount++;
+ failedFiles.push(filePath);
+ }
+ }
+ }
+}
+
+runTestsInDirectory(testDirectory);
+
+console.log('--- Grammar Test Results ---');
+console.log(`Success count: ${successCount}`);
+console.log(`Failure count: ${failureCount}`);
+if (failureCount > 0) {
+ console.log('Failed files:');
+ for (const failedFile of failedFiles) {
+ console.log(failedFile);
+ }
+}
\ No newline at end of file
diff --git a/arkguard/src/ArkObfuscator.ts b/arkguard/src/ArkObfuscator.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cf20c9b9594267afef1b7b000cf62c118f7b4f5a
--- /dev/null
+++ b/arkguard/src/ArkObfuscator.ts
@@ -0,0 +1,402 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import {
+ createPrinter,
+ createProgram,
+ createSourceFile, createTextWriter,
+ forEachChild,
+ isIdentifier,
+ isTypePredicateNode,
+ ScriptTarget,
+ transform,
+ createObfTextSingleLineWriter,
+} from 'typescript';
+
+import type {
+ CompilerOptions,
+ EmitTextWriter,
+ JSDocReturnTag,
+ JSDocSignature,
+ Node,
+ Printer,
+ PrinterOptions,
+ Program,
+ Signature,
+ SignatureDeclaration,
+ SourceFile,
+ SourceMapGenerator,
+ TransformationResult,
+ TransformerFactory,
+ TypeChecker,
+ TypeNode
+} from 'typescript';
+
+import * as fs from 'fs';
+import path from 'path';
+import sourceMap from 'source-map';
+
+import type {IOptions} from './configs/IOptions';
+import {FileUtils} from './utils/FileUtils';
+import {TransformerManager} from './transformers/TransformerManager';
+import {getSourceMapGenerator} from './utils/SourceMapUtil';
+
+import {
+ getMapFromJson,
+ NAME_CACHE_SUFFIX,
+ PROPERTY_CACHE_FILE,
+ readCache, writeCache
+} from './utils/NameCacheUtil';
+import {ListUtil} from './utils/ListUtil';
+import {needReadApiInfo, getReservedProperties, readProjectProperties} from './common/ApiReader';
+import {ApiExtractor} from './common/ApiExtractor';
+import es6Info from './configs/preset/es6_reserved_properties.json';
+
+export const renameIdentifierModule = require('./transformers/rename/RenameIdentifierTransformer');
+export const renamePropertyModule = require('./transformers/rename/RenamePropertiesTransformer');
+
+export { getMapFromJson, readProjectProperties };
+export class ArkObfuscator {
+ // A text writer of Printer
+ private mTextWriter: EmitTextWriter;
+
+ // A list of source file path
+ private readonly mSourceFiles: string[];
+
+ // Path of obfuscation configuration file.
+ private readonly mConfigPath: string;
+
+ // Compiler Options for typescript,use to parse ast
+ private readonly mCompilerOptions: CompilerOptions;
+
+ // User custom obfuscation profiles.
+ private mCustomProfiles: IOptions;
+
+ private mTransformers: TransformerFactory[];
+
+ private mNeedCollectNarrowFunction: boolean;
+
+ public constructor(sourceFiles?: string[], configPath?: string) {
+ this.mSourceFiles = sourceFiles;
+ this.mConfigPath = configPath;
+ this.mCompilerOptions = {};
+ this.mTransformers = [];
+ }
+
+ /**
+ * init ArkObfuscator according to user config
+ * should be called after constructor
+ */
+ public init(config?: any): boolean {
+ if (!this.mConfigPath && !config) {
+ return false;
+ }
+
+ if (this.mConfigPath) {
+ config = FileUtils.readFileAsJson(this.mConfigPath);
+ }
+
+ this.mCustomProfiles = config as IOptions;
+
+
+
+ if (this.mCustomProfiles.mCompact) {
+ this.mTextWriter = createObfTextSingleLineWriter();
+ } else {
+ this.mTextWriter = createTextWriter('\n');
+ }
+
+ if (this.mCustomProfiles.mEnableSourceMap) {
+ this.mCompilerOptions.sourceMap = true;
+ }
+
+
+ // load transformers
+ this.mTransformers = TransformerManager.getInstance().loadTransformers(this.mCustomProfiles);
+
+ // check need collect narrow function names
+ this.mNeedCollectNarrowFunction = this.checkNeedCollectNarrowFunction();
+
+ if (needReadApiInfo(this.mCustomProfiles)) {
+ this.mCustomProfiles.mNameObfuscation.mReservedProperties = ListUtil.uniqueMergeList(
+ this.mCustomProfiles.mNameObfuscation.mReservedProperties,
+ this.mCustomProfiles.mNameObfuscation.mReservedNames,
+ es6Info);
+ }
+
+ return true;
+ }
+
+ /**
+ * Obfuscate all the source files.
+ */
+ public async obfuscateFiles() {
+ if (!path.isAbsolute(this.mCustomProfiles.mOutputDir)) {
+ this.mCustomProfiles.mOutputDir = path.join(path.dirname(this.mConfigPath), this.mCustomProfiles.mOutputDir);
+ }
+ if (this.mCustomProfiles.mOutputDir && !fs.existsSync(this.mCustomProfiles.mOutputDir)) {
+ fs.mkdirSync(this.mCustomProfiles.mOutputDir);
+ }
+
+ readProjectProperties(this.mSourceFiles, this.mCustomProfiles);
+
+ this.readPropertyCache(this.mCustomProfiles.mOutputDir);
+ // support directory and file obfuscate
+ for (const sourcePath of this.mSourceFiles) {
+ if (!fs.existsSync(sourcePath)) {
+ console.error(`File ${FileUtils.getFileName(sourcePath)} is not found.`);
+ return;
+ }
+
+ if (fs.lstatSync(sourcePath).isFile()) {
+ await this.obfuscateFile(sourcePath, this.mCustomProfiles.mOutputDir);
+ continue;
+ }
+
+ const dirPrefix: string = FileUtils.getPrefix(sourcePath);
+ await this.obfuscateDir(sourcePath, dirPrefix);
+ }
+ this.producePropertyCache(this.mCustomProfiles.mOutputDir);
+ }
+
+ /**
+ * obfuscate directory
+ * @private
+ */
+ private async obfuscateDir(dirName: string, dirPrefix: string): Promise {
+ const currentDir: string = FileUtils.getPathWithoutPrefix(dirName, dirPrefix);
+ const newDir: string = path.join(this.mCustomProfiles.mOutputDir, currentDir);
+ if (!fs.existsSync(newDir)) {
+ fs.mkdirSync(newDir);
+ }
+
+ const fileNames: string[] = fs.readdirSync(dirName);
+ for (let fileName of fileNames) {
+ const filePath: string = path.join(dirName, fileName);
+ if (fs.lstatSync(filePath).isFile()) {
+ await this.obfuscateFile(filePath, newDir);
+ continue;
+ }
+
+ if (fileName === 'node_modules' || fileName === 'oh_modules') {
+ continue;
+ }
+
+ await this.obfuscateDir(filePath, dirPrefix);
+ }
+ }
+
+ private checkNeedCollectNarrowFunction(): boolean {
+ return this.mCustomProfiles.mControlFlowFlattening &&
+ this.mCustomProfiles.mControlFlowFlattening.mEnable &&
+ this.mCustomProfiles.mInstructionObfuscation &&
+ this.mCustomProfiles.mInstructionObfuscation.mEnable;
+ }
+
+ private collectNarrowFunctions(file: string): void {
+ if (!this.mNeedCollectNarrowFunction) {
+ return;
+ }
+
+ let results: Set = new Set();
+
+ let program: Program = createProgram([file], this.mCompilerOptions);
+ let checker: TypeChecker = program.getTypeChecker();
+ let visit = (node: Node): void => {
+ if (!node) {
+ return;
+ }
+
+ if (isIdentifier(node)) {
+ let type: Signature = checker.getTypeAtLocation(node).getCallSignatures()[0];
+ let declaration: SignatureDeclaration | JSDocSignature = type?.declaration;
+ let retType: TypeNode | JSDocReturnTag = declaration?.type;
+ if (retType && isTypePredicateNode(retType)) {
+ results.add(node.text);
+ }
+ }
+
+ forEachChild(node, visit);
+ };
+
+ let ast: SourceFile = program.getSourceFile(file);
+ visit(ast);
+
+ this.mCustomProfiles.mNarrowFunctionNames = [...results];
+ }
+
+ private readNameCache(sourceFile: string, outputDir: string): void {
+ if (!this.mCustomProfiles.mNameObfuscation.mEnable || !this.mCustomProfiles.mEnableNameCache) {
+ return;
+ }
+
+ const nameCachePath: string = path.join(outputDir, FileUtils.getFileName(sourceFile) + NAME_CACHE_SUFFIX);
+ const nameCache: Object = readCache(nameCachePath);
+
+ renameIdentifierModule.historyNameCache = getMapFromJson(nameCache);
+ }
+
+ private readPropertyCache(outputDir: string): void {
+ const propertyCachePath: string = path.join(outputDir, PROPERTY_CACHE_FILE);
+ const propertyCache: Object = readCache(propertyCachePath);
+ if (!propertyCache) {
+ return;
+ }
+
+ if (this.mCustomProfiles.mNameObfuscation.mRenameProperties) {
+ renamePropertyModule.historyMangledTable = getMapFromJson(propertyCache);
+ }
+ }
+
+ private produceNameCache(namecache: any, sourceFile: string, outputDir: string): void {
+ const nameCachePath: string = path.join(outputDir, FileUtils.getFileName(sourceFile) + NAME_CACHE_SUFFIX);
+ fs.writeFileSync(nameCachePath, JSON.stringify(namecache, null, 2));
+ }
+
+ private producePropertyCache(outputDir: string): void {
+ if (this.mCustomProfiles.mNameObfuscation.mRenameProperties) {
+ const propertyCachePath: string = path.join(outputDir, PROPERTY_CACHE_FILE);
+ writeCache(renamePropertyModule.globalMangledTable, propertyCachePath);
+ }
+ }
+
+ async mergeSourcrMap(originMap: sourceMap.RawSourceMap, newMap: sourceMap.RawSourceMap): Promise {
+ if (!originMap) {
+ return newMap;
+ }
+ if (!newMap) {
+ return originMap;
+ }
+ const originConsumer: sourceMap.SourceMapConsumer = await new sourceMap.SourceMapConsumer(originMap);
+ const newConsumer: sourceMap.SourceMapConsumer = await new sourceMap.SourceMapConsumer(newMap);
+ const newMappingList: sourceMap.MappingItem[] = [];
+ newConsumer.eachMapping((mapping: sourceMap.MappingItem) => {
+ if (mapping.originalLine == null) {
+ return;
+ }
+ const originalPos = originConsumer.originalPositionFor({line: mapping.originalLine, column: mapping.originalColumn});
+ if (originalPos.source == null) {
+ return;
+ }
+ mapping.originalLine = originalPos.line;
+ mapping.originalColumn = originalPos.column;
+ newMappingList.push(mapping);
+ });
+ const updatedGenerator: sourceMap.SourceMapGenerator = sourceMap.SourceMapGenerator.fromSourceMap(newConsumer);
+ updatedGenerator['_file'] = originMap.file;
+ updatedGenerator['_mappings']['_array'] = newMappingList;
+ return JSON.parse(updatedGenerator.toString());
+ }
+
+ /**
+ * A Printer to output obfuscated codes.
+ */
+ public createObfsPrinter(): Printer {
+ // set print options
+ let printerOptions: PrinterOptions = {};
+ if (this.mCustomProfiles.mRemoveComments) {
+ printerOptions.removeComments = true;
+ }
+ return createPrinter(printerOptions);
+ }
+
+ /**
+ * Obfuscate single source file
+ *
+ * @param sourceFile single source file path
+ * @param outputDir
+ */
+ public async obfuscateFile(sourceFilePath: string, outputDir: string): Promise {
+ const fileName: string = FileUtils.getFileName(sourceFilePath);
+ let suffix: string = FileUtils.getFileExtension(sourceFilePath);
+
+ if ((suffix !== 'js' && suffix !== 'ts') || fileName.endsWith('.d.ts')) {
+ fs.copyFileSync(sourceFilePath, path.join(outputDir, fileName));
+ return;
+ }
+
+ // Advanced confusion requires calling this function
+ this.collectNarrowFunctions(sourceFilePath);
+
+ let content: string = FileUtils.readFile(sourceFilePath);
+ this.readNameCache(sourceFilePath, outputDir);
+ const mixedInfo: {content: string, sourceMap, nameCache: Map} = await this.obfuscate(content, sourceFilePath);
+
+ if (outputDir) {
+ fs.writeFileSync(path.join(outputDir, FileUtils.getFileName(sourceFilePath)), mixedInfo.content);
+ if (this.mCustomProfiles.mEnableSourceMap && mixedInfo.sourceMap) {
+ fs.writeFileSync(path.join(outputDir, FileUtils.getFileName(sourceFilePath) + '.map'), JSON.stringify(mixedInfo.sourceMap, null, 2));
+ }
+ if (this.mCustomProfiles.mEnableNameCache && this.mCustomProfiles.mEnableNameCache) {
+ this.produceNameCache(mixedInfo.nameCache, sourceFilePath, outputDir);
+ }
+ }
+
+ }
+
+ /**
+ * Obfuscate ast of a file.
+ * @param ast ast of a source file
+ */
+ public async obfuscate(content: SourceFile | string, sourceFilePath: string, previousStageSourceMap?: any,
+ historyNameCache?: Map): Promise {
+ let ast: SourceFile;
+ if (typeof content === 'string') {
+ ast = createSourceFile(sourceFilePath, content, ScriptTarget.ES2015, true);
+ }
+ else {
+ ast = content;
+ }
+
+ if (ast.statements.length === 0) {
+ return ast;
+ }
+
+ if (historyNameCache && this.mCustomProfiles.mNameObfuscation) {
+ renameIdentifierModule.historyNameCache = historyNameCache;
+ }
+
+ let transformedResult: TransformationResult = transform(ast, this.mTransformers, this.mCompilerOptions);
+ ast = transformedResult.transformed[0] as SourceFile;
+
+ // convert ast to output source file and generate sourcemap if needed.
+ let sourceMapGenerator: SourceMapGenerator = undefined;
+ if (this.mCustomProfiles.mEnableSourceMap) {
+ sourceMapGenerator = getSourceMapGenerator(sourceFilePath);
+ }
+
+ this.createObfsPrinter().writeFile(ast, this.mTextWriter, sourceMapGenerator);
+
+ const result = { content: this.mTextWriter.getText() };
+
+ if (this.mCustomProfiles.mEnableSourceMap) {
+ let sourceMapJson = sourceMapGenerator.toJSON();
+ sourceMapJson['sourceRoot'] = '';
+ sourceMapJson.file = path.basename(sourceFilePath);
+ if (previousStageSourceMap) {
+ sourceMapJson = await this.mergeSourcrMap(previousStageSourceMap, sourceMapJson as sourceMap.RawSourceMap);
+ }
+ result['sourceMap'] = sourceMapJson;
+ }
+ if (this.mCustomProfiles.mEnableNameCache) {
+ result['nameCache'] = Object.fromEntries(renameIdentifierModule.nameCache);
+ }
+ // clear cache of text writer
+ this.mTextWriter.clear();
+ renameIdentifierModule.nameCache.clear();
+ return result;
+ }
+}
+export {ApiExtractor};
\ No newline at end of file
diff --git a/arkguard/src/IObfuscator.ts b/arkguard/src/IObfuscator.ts
new file mode 100644
index 0000000000000000000000000000000000000000..712fb10dcdfb0efaee9436529fdd26cfc35dec4f
--- /dev/null
+++ b/arkguard/src/IObfuscator.ts
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+export interface IObfuscator {
+ /**
+ * interface for obfuscating source code
+ *
+ * @param code string sequence of source code
+ */
+ obfuscate(code: string): string;
+
+ /**
+ * interface for obfuscating source file
+ *
+ * @param file path of single source file.
+ */
+ obfuscateFile(file: string): string;
+
+ /**
+ * interface for obfuscating source files;
+ *
+ * @param files a list of source files
+ */
+ obfuscateFiles(files: string[]): string[];
+}
diff --git a/arkguard/src/cli/SecHarmony.ts b/arkguard/src/cli/SecHarmony.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9ec44cfa9f4d8df9eb21827aa3a7bef52deb83d6
--- /dev/null
+++ b/arkguard/src/cli/SecHarmony.ts
@@ -0,0 +1,62 @@
+#!/usr/bin/env node
+
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import {program} from 'commander';
+import * as path from 'path';
+
+import {ArkObfuscator} from '../ArkObfuscator';
+
+/**
+ * Main Entry of Obfuscation in
+ */
+const minParametersNum: number = 3;
+(function (): void {
+ if (process.argv.length < minParametersNum) {
+ console.error('Too few input parameters.');
+ console.error('Usage: SecHarmony [input files] [options]');
+ return;
+ }
+
+ initOptionsSetting();
+
+ let configPath: string = program.opts()?.configPath;
+ configPath = path.resolve(configPath);
+ let fileList: Array = [];
+ program.args.forEach((value) => {
+ const resolved: string = path.resolve(value);
+ fileList.push(resolved);
+ });
+
+ let obfuscator: ArkObfuscator = new ArkObfuscator(fileList, configPath);
+ const initSuccess: boolean = obfuscator.init();
+ if (!initSuccess) {
+ console.error('init from config file error.');
+ return;
+ }
+
+ obfuscator.obfuscateFiles();
+})();
+
+function initOptionsSetting(): void {
+ program.name('SecHarmony')
+ .version('1.0.0')
+ .description('A tool to obfuscate open harmony application written by Javascript or Typescript.')
+ .usage('Usage: SecHarmony [input files] [options]')
+ .option('-v, --version', 'show version information.')
+ .option('-cp, --config-path ', 'obfuscation configuration for open harmony application.')
+ .parse();
+}
diff --git a/arkguard/src/common/ApiExtractor.ts b/arkguard/src/common/ApiExtractor.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9d15871324d52d613011a1b734eeb2e64706bdc5
--- /dev/null
+++ b/arkguard/src/common/ApiExtractor.ts
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import {
+ createSourceFile,
+ forEachChild,
+ isBinaryExpression,
+ isClassDeclaration,
+ isEnumDeclaration,
+ isEnumMember,
+ isExportAssignment,
+ isExportDeclaration,
+ isExportSpecifier,
+ isFunctionDeclaration,
+ isInterfaceDeclaration,
+ isMethodDeclaration,
+ isMethodSignature,
+ isModuleDeclaration,
+ isPropertyDeclaration,
+ isPropertySignature,
+ isTypeAliasDeclaration,
+ isVariableDeclaration,
+ isVariableStatement,
+ Node,
+ ScriptKind,
+ ScriptTarget,
+ SyntaxKind
+} from 'typescript';
+
+import type {
+ ModifiersArray,
+ SourceFile
+} from 'typescript';
+
+import fs from 'fs';
+import path from 'path';
+
+export namespace ApiExtractor {
+ interface KeywordInfo {
+ hasExport: boolean,
+ hasDeclare: boolean
+ }
+
+ export enum ApiType {
+ API = 1,
+ COMPONENT = 2,
+ PROJECTDEPENDENCY = 3,
+ PROJECT = 4
+ }
+
+ let mExportNameList: string[] = [];
+ let mCurrentExportNameList: string[] = [];
+ export let mPropertyList: string[] = [];
+ export let mNameList: string[] = [];
+
+ /**
+ * filter classes or interfaces with export, default, etc
+ */
+ const getKeyword = function (modifiers: ModifiersArray): KeywordInfo {
+ let hasExport: boolean = false;
+ let hasDeclare: boolean = false;
+
+ for (const modifier of modifiers) {
+ if (modifier.kind === SyntaxKind.ExportKeyword) {
+ hasExport = true;
+ }
+
+ if (modifier.kind === SyntaxKind.DeclareKeyword) {
+ hasDeclare = true;
+ }
+ }
+
+ return {hasExport: hasExport, hasDeclare: hasDeclare};
+ };
+
+ /**
+ * get export name list
+ * @param astNode
+ */
+ const visitExport = function (astNode): void {
+ if (isExportAssignment(astNode)) {
+ if (!mCurrentExportNameList.includes(astNode.expression.getText())) {
+ mCurrentExportNameList.push(astNode.expression.getText());
+ }
+
+ return;
+ }
+
+ if (astNode.modifiers === undefined) {
+ return;
+ }
+
+ let {hasExport, hasDeclare} = getKeyword(astNode.modifiers);
+ if (!hasExport) {
+ return;
+ }
+
+ if (astNode.name) {
+ if (!mCurrentExportNameList.includes(astNode.name.getText())) {
+ mCurrentExportNameList.push(astNode.name.getText());
+ }
+
+ return;
+ }
+
+ if (hasDeclare && astNode.declarationList &&
+ !mCurrentExportNameList.includes(astNode.declarationList.declarations[0].name.getText())) {
+ mCurrentExportNameList.push(astNode.declarationList.declarations[0].name.getText());
+ }
+ };
+
+ const checkPropertyNeedVisit = function (astNode): boolean {
+ if (astNode.name && !mCurrentExportNameList.includes(astNode.name.getText())) {
+ return false;
+ }
+
+ if (astNode.name === undefined) {
+ if (astNode.modifiers === undefined) {
+ return false;
+ }
+ let {hasDeclare} = getKeyword(astNode.modifiers);
+ if (hasDeclare && astNode.declarationList &&
+ !mCurrentExportNameList.includes(astNode.declarationList.declarations[0].name.getText())) {
+ return false;
+ }
+ }
+
+ return true;
+ };
+
+ const visitChildNode = function (astNode): void {
+ if (isClassDeclaration(astNode) ||
+ isInterfaceDeclaration(astNode) ||
+ isEnumDeclaration(astNode) ||
+ isTypeAliasDeclaration(astNode) ||
+ isPropertySignature(astNode) ||
+ isMethodSignature(astNode) ||
+ isFunctionDeclaration(astNode) ||
+ isMethodDeclaration(astNode) ||
+ isPropertyDeclaration(astNode) ||
+ isEnumMember(astNode) ||
+ isExportSpecifier(astNode) ||
+ isVariableDeclaration(astNode)) {
+ if (astNode.name !== undefined ) {
+ const name = astNode.name.getText();
+ if (!mPropertyList.includes(name)) {
+ mPropertyList.push(name);
+ }
+ if (!mNameList.includes(name)) {
+ mNameList.push(name);
+ }
+ }
+ }
+
+ astNode.forEachChild((childNode) => {
+ visitChildNode(childNode);
+ });
+ };
+
+ /**
+ * visit ast of a file and collect api list
+ * @param astNode node of ast
+ */
+ const visitPropertyAndName = function (astNode): void {
+ if (!checkPropertyNeedVisit(astNode)) {
+ return;
+ }
+
+ visitChildNode(astNode);
+ };
+
+ const visitProjectNode = function (astNode): void {
+ if (astNode.modifiers) {
+ let {hasExport} = getKeyword(astNode.modifiers);
+ if (!hasExport) {
+ return;
+ }
+
+ if (astNode.name !== undefined) {
+ if (!mPropertyList.includes(astNode.name.getText())) {
+ mPropertyList.push(astNode.name.getText());
+ }
+
+ if (isModuleDeclaration(astNode)) {
+ astNode.forEachChild((childNode) => {
+ visitProjectNode(childNode);
+ });
+ }
+ return;
+ }
+
+ if (isVariableStatement(astNode)) {
+ astNode.declarationList.forEachChild((child) => {
+ if (isVariableDeclaration(child) && !mPropertyList.includes(child.name.getText())) {
+ mPropertyList.push(child.name.getText());
+ }
+ });
+ }
+
+ return;
+ }
+
+ if (isExportAssignment(astNode)) {
+ if (isBinaryExpression(astNode.expression)) {
+ if (!mPropertyList.includes(astNode.expression.left.getText())) {
+ mPropertyList.push(astNode.expression.left.getText());
+ }
+ }
+ return;
+ }
+
+ if (isExportDeclaration(astNode)) {
+ if (astNode.exportClause && astNode.exportClause.kind === SyntaxKind.NamedExports) {
+ astNode.exportClause.forEachChild((child) => {
+ if (!isExportSpecifier(child)) {
+ return;
+ }
+
+ if (!mPropertyList.includes(child.name.getText())) {
+ mPropertyList.push(child.name.getText());
+ }
+ });
+ }
+
+ return;
+ }
+
+ astNode.forEachChild((childNode) => {
+ visitProjectNode(childNode);
+ });
+ };
+
+ const visitProjectProperty = function (astNode): void {
+ visitProjectNode(astNode);
+ };
+
+ /**
+ * parse file to api list and save to json object
+ * @param fileName file name of api file
+ * @param apiType
+ * @private
+ */
+ const parseFile = function (fileName: string, apiType: ApiType): void {
+ const scriptKind: ScriptKind = fileName.endsWith('.ts') ? ScriptKind.TS : ScriptKind.JS;
+ const sourceFile: SourceFile = createSourceFile(fileName, fs.readFileSync(fileName).toString(), ScriptTarget.ES2015, true, scriptKind);
+
+ // get export name list
+ switch (apiType) {
+ case ApiType.PROJECTDEPENDENCY:
+ case ApiType.COMPONENT:
+ forEachChild(sourceFile, visitChildNode);
+ break;
+ case ApiType.API:
+ mCurrentExportNameList.length = 0;
+ forEachChild(sourceFile, visitExport);
+
+ mCurrentExportNameList.forEach((value) => {
+ if (!mExportNameList.includes(value)) {
+ mExportNameList.push(value);
+ mNameList.push(value);
+ }
+ });
+
+ forEachChild(sourceFile, visitPropertyAndName);
+ mCurrentExportNameList.length = 0;
+ break;
+ case ApiType.PROJECT:
+ if (fileName.endsWith('.d.ts')) {
+ forEachChild(sourceFile, visitChildNode);
+ break;
+ }
+
+ mCurrentExportNameList.length = 0;
+ forEachChild(sourceFile, visitProjectProperty);
+ mCurrentExportNameList.length = 0;
+ break;
+ default:
+ break;
+ }
+ };
+
+ /**
+ * traverse files of api directory
+ * @param apiPath api directory path
+ * @param apiType
+ * @private
+ */
+ export const traverseApiFiles = function (apiPath: string, apiType: ApiType): void {
+ let fileNames: string[] = [];
+ if (fs.lstatSync(apiPath).isDirectory()) {
+ fileNames = fs.readdirSync(apiPath);
+ for (let fileName of fileNames) {
+ let filePath: string = path.join(apiPath, fileName);
+ if (fs.lstatSync(filePath).isDirectory()) {
+ if (fileName === 'node_modules' || fileName === 'oh_modules') {
+ continue;
+ }
+
+ traverseApiFiles(filePath, apiType);
+ continue;
+ }
+
+ if (fs.lstatSync(filePath).isSymbolicLink()) {
+ filePath = fs.readlinkSync(filePath);
+ if (fs.lstatSync(filePath).isDirectory()) {
+ traverseApiFiles(filePath, apiType);
+ continue;
+ }
+ }
+
+ if ((apiType !== ApiType.PROJECT) && !filePath.endsWith('.d.ts')) {
+ continue;
+ }
+
+ if (apiType === ApiType.PROJECT && !filePath.endsWith('.ts') && !filePath.endsWith('.js')) {
+ continue;
+ }
+
+ parseFile(filePath, apiType);
+ }
+ }
+ else {
+ parseFile(apiPath, apiType);
+ }
+ };
+
+ /**
+ * desc: parse openHarmony sdk to get api list
+ * @param version version of api, e.g. version 5.0.1.0 for api 9
+ * @param sdkPath sdk real path of openHarmony
+ * @param isEts true for ets, false for js
+ * @param outputDir: sdk api output directory
+ */
+ export function parseOhSdk(sdkPath: string, version: string, isEts: boolean, outputDir: string): void {
+ mExportNameList.length = 0;
+ mPropertyList.length = 0;
+
+ // visit api directory
+ const apiPath: string = path.join(sdkPath, (isEts ? 'ets' : 'js'), version, 'api');
+ traverseApiFiles(apiPath, ApiType.API);
+
+ // visit component directory if ets
+ if (isEts) {
+ const componentPath: string = path.join(sdkPath, 'ets', version, 'component');
+ traverseApiFiles(componentPath, ApiType.COMPONENT);
+ }
+
+ // visit the UI conversion API
+ const uiConversionPath: string = path.join(sdkPath, (isEts ? 'ets' : 'js'), version, 'build-tools', 'ets-loader', 'lib', 'pre_define.js');
+ extractStringsFromFile(uiConversionPath);
+
+ writeToFile(mExportNameList, path.join(outputDir, 'nameReserved.json'));
+ writeToFile(mPropertyList, path.join(outputDir, 'propertiesReserved.json'));
+ mExportNameList.length = 0;
+ mPropertyList.length = 0;
+ }
+
+ export function extractStringsFromFile(filePath: string): void {
+ let collections: string[] = [];
+ const fileContent = fs.readFileSync(filePath, 'utf-8');
+ const regex = /"([^"]*)"/g;
+ const matches = fileContent.match(regex);
+
+ if (matches) {
+ collections = matches.map(match => match.slice(1, -1));
+ }
+
+ mPropertyList = mPropertyList.concat(collections);
+ mNameList = mNameList.concat(collections);
+ }
+
+ /**
+ * parse common project or file to extract exported api list
+ * @return reserved api names
+ */
+ export function parseCommonProject(projectPath): string[] {
+ mPropertyList.length = 0;
+
+ if (fs.lstatSync(projectPath).isFile()) {
+ if (projectPath.endsWith('.ts') || projectPath.endsWith('.js')) {
+ parseFile(projectPath, ApiType.PROJECT);
+ }
+ } else {
+ traverseApiFiles(projectPath, ApiType.PROJECT);
+ }
+
+ const reservedProperties: string[] = [...mPropertyList];
+ mPropertyList.length = 0;
+
+ return reservedProperties;
+ }
+
+ /**
+ * parse api of third party libs like libs in node_modules
+ * @param libPath
+ */
+ export function parseThirdPartyLibs(libPath): string[] {
+ mPropertyList.length = 0;
+
+ if (fs.lstatSync(libPath).isFile()) {
+ if (libPath.endsWith('.ts') || libPath.endsWith('.js')) {
+ parseFile(libPath, ApiType.PROJECTDEPENDENCY);
+ }
+ } else {
+ traverseApiFiles(libPath, ApiType.PROJECTDEPENDENCY);
+ }
+
+ const reservedProperties: string[] = [...mPropertyList];
+ mPropertyList.length = 0;
+
+ return reservedProperties;
+ }
+
+ /**
+ * save api json object to file
+ * @private
+ */
+ export function writeToFile(reservedProperties: string[], outputPath: string): void {
+ let str: string = JSON.stringify(reservedProperties, null, '\t');
+ fs.writeFileSync(outputPath, str);
+ }
+}
+
diff --git a/arkguard/src/common/ApiReader.ts b/arkguard/src/common/ApiReader.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3c8542d14f6ff46a2d50dbd7e615b112649ea01f
--- /dev/null
+++ b/arkguard/src/common/ApiReader.ts
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import path from 'path';
+import fs from 'fs';
+import {FileUtils} from '../utils/FileUtils';
+import {ApiExtractor} from './ApiExtractor';
+import {ListUtil} from '../utils/ListUtil';
+import type {IOptions} from '../configs/IOptions';
+import es6Info from '../configs/preset/es6_reserved_properties.json';
+
+/**
+ * if rename property is not open, api read and extract can be skipped
+ *
+ * init plugin, read api info of openHarmony sdk and generate file of reserved name, property and string.
+ * @param sdkDir absolute path like D:\\HuaweiApp\\ohsdk
+ * @param outputDir
+ */
+export function initPlugin(sdkDir: string, outputDir: string): void {
+ // create sdk api file if not exist
+ const ohSdkPath: string = path.resolve(sdkDir);
+ if (!ohSdkPath) {
+ console.error('SDK path is not found.');
+ }
+
+ const apiVersions: string[] = [''];
+
+ apiVersions.forEach((versionString) => {
+ ApiExtractor.parseOhSdk(ohSdkPath, versionString, true, outputDir);
+ });
+}
+
+
+export function getReservedProperties(apiSavedPath?: string): string[] {
+ let reservedProperties: string[] = [];
+ if (apiSavedPath) {
+ reservedProperties = readOhReservedProperties(apiSavedPath);
+ }
+ // read language reserved property
+ reservedProperties = [...reservedProperties, ...es6Info];
+ const propertySet: Set = new Set(reservedProperties);
+
+ return Array.from(propertySet);
+}
+
+/**
+ * read reserved properties of openHarmony sdk
+ */
+export function readOhReservedProperties(apiSavedPath: string): string[] {
+ // 1. read oh sdk api reserved property and string
+ let reservedProperties: string[] = [];
+
+ const sdkApiDir: string = path.resolve(__dirname, apiSavedPath);
+ const fileNames: string[] = fs.readdirSync(sdkApiDir);
+ for (const fileName of fileNames) {
+ const filePath: string = path.join(sdkApiDir, fileName);
+ if (!fs.lstatSync(filePath).isFile()) {
+ continue;
+ }
+
+ const properties: string[] = FileUtils.readFileAsJson(filePath);
+ if (properties === undefined) {
+ console.error('read openHarmony reserved property file error.');
+ continue;
+ }
+
+ reservedProperties = [...reservedProperties, ...properties];
+ }
+ return reservedProperties;
+}
+
+/**
+ * need read api info or not
+ * @param customProfiles
+ */
+export function needReadApiInfo(customProfiles: IOptions): boolean {
+ return customProfiles.mNameObfuscation &&
+ customProfiles.mNameObfuscation.mEnable &&
+ customProfiles.mNameObfuscation.mRenameProperties;
+}
+
+/**
+ * read project reserved properties
+ * @param projectPaths can be dir or file
+ * @param customProfiles
+ */
+export function readProjectProperties(projectPaths: string[], customProfiles: IOptions): void {
+ if (!needReadApiInfo(customProfiles)) {
+ return;
+ }
+
+ for (const projectPath of projectPaths) {
+ if (!fs.existsSync(projectPath)) {
+ console.error(`File ${FileUtils.getFileName(projectPath)} is not found.`);
+ return;
+ }
+
+ const projProperties: string[] = ApiExtractor.parseCommonProject(projectPath);
+ const sdkProperties: string[] = readThirdPartyLibProperties(projectPath);
+
+ // read project code export names
+ customProfiles.mNameObfuscation.mReservedProperties = ListUtil.uniqueMergeList(projProperties,
+ customProfiles.mNameObfuscation.mReservedProperties);
+
+ // read project lib export names
+ if (sdkProperties) {
+ customProfiles.mNameObfuscation.mReservedProperties = ListUtil.uniqueMergeList(sdkProperties,
+ customProfiles.mNameObfuscation.mReservedProperties);
+ }
+ }
+}
+
+function readThirdPartyLibProperties(projectPath: string): string[] {
+ let reservedProperties: string[] = [];
+
+ if (!fs.lstatSync(projectPath).isDirectory()) {
+ return undefined;
+ }
+
+ // find third party lib and extract reserved names
+ const fileNames: string[] = fs.readdirSync(projectPath);
+ const hasNodeModules: boolean = fileNames.includes('node_modules');
+ const hasOHModules: boolean = fileNames.includes('oh_modules');
+ if (!hasNodeModules && !hasOHModules) {
+ return undefined;
+ }
+ if (hasNodeModules && hasOHModules) {
+ throw new Error(`There are both node_modules and oh_modules folders in ${projectPath}`);
+ }
+
+ let filePath: string = '';
+ if (hasNodeModules) {
+ filePath = path.join(projectPath, 'node_modules');
+ }
+ else {
+ filePath = path.join(projectPath, 'oh_modules');
+ }
+
+ const properties: string[] = ApiExtractor.parseThirdPartyLibs(filePath);
+ reservedProperties = [...reservedProperties, ...properties];
+ const propertySet: Set = new Set(reservedProperties);
+
+ return Array.from(propertySet);
+}
diff --git a/arkguard/src/configs/ArkGuardOptions.ts b/arkguard/src/configs/ArkGuardOptions.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ced1afce585109aea81c094a0598825b46ad62d0
--- /dev/null
+++ b/arkguard/src/configs/ArkGuardOptions.ts
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import type {IOptions} from './IOptions';
+
+export interface ArkGuardOptions {
+ /**
+ * path of open harmony sdk
+ */
+ sdkPath?: string,
+
+ /**
+ * api version of open harmony sdk
+ */
+ apiVersion?: string,
+
+ /**
+ * Protection level specified by user
+ */
+ protectedLevel?: boolean;
+
+ /**
+ * whether to turn on source map function.
+ */
+ sourceMap?: boolean,
+ /**
+ * specify the path of name cache file, use in hot update.
+ */
+ nameCache?: string,
+
+ /**
+ * output directory for obfuscated results.
+ */
+ outDir?: string,
+
+ /**
+ * obfuscation options
+ */
+ obfuscations?: IOptions,
+}
diff --git a/arkguard/src/configs/IBogusControlFlowOption.ts b/arkguard/src/configs/IBogusControlFlowOption.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fcc40f24a27178b8248c78e2ec2ed7a89680008b
--- /dev/null
+++ b/arkguard/src/configs/IBogusControlFlowOption.ts
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+/**
+ * Generation type of the inserted block statement
+ */
+export enum BogusBlockType {
+ /**
+ * Use other available block and rename variables in block
+ */
+ OTHER_BLOCK_RENAME = 1,
+
+ /**
+ * Use a deformation of current block, replaces with some basic operations
+ */
+ CURRENT_BLOCK_DEFORM = 2,
+}
+
+export interface IBogusControlFlowOption {
+ /**
+ * Whether to enable bogus control flow obfuscation
+ */
+ readonly mEnable: boolean;
+
+ /**
+ * Probability of inserting bogus control flow into the target node
+ */
+ readonly mThreshold: number;
+
+ /**
+ * skip obfuscation in loop for performance
+ */
+ readonly mSkipLoop?: boolean;
+
+ /**
+ * Whether to use opaque predicates
+ */
+ readonly mUseOpaquePredicate: boolean;
+
+ /**
+ * Generation type of the inserted bogus block.
+ */
+ readonly mInsertBlockType: BogusBlockType;
+}
diff --git a/arkguard/src/configs/IControlFlowFatteningOption.ts b/arkguard/src/configs/IControlFlowFatteningOption.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d4ead7bc3aef6107fb0e3a1ad0c9c92950d48b58
--- /dev/null
+++ b/arkguard/src/configs/IControlFlowFatteningOption.ts
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+export interface IControlFlowFatteningOption {
+ /**
+ * Whether to enable control flow obfuscation
+ */
+ readonly mEnable: boolean;
+
+ /**
+ * Probability of control flow obfuscation
+ */
+ readonly mThreshold: number;
+
+ /**
+ * skip obfuscation in loop for performance
+ */
+ readonly mSkipLoop?: boolean;
+
+ /**
+ * advance switch
+ */
+ readonly mAdvance?: boolean;
+
+ /**
+ * Whether to flatten if statement
+ */
+ readonly mIfFlattening?: boolean;
+
+ /**
+ * Whether to flatten switch statement
+ */
+ readonly mSwitchFlatting?: boolean;
+
+ /**
+ * Whether to convert case constants to expression
+ */
+ readonly mCaseToExpression?: boolean;
+}
diff --git a/arkguard/src/configs/IDataObfuscationOption.ts b/arkguard/src/configs/IDataObfuscationOption.ts
new file mode 100644
index 0000000000000000000000000000000000000000..74c1de9a699f582eca614e151cd3a3cecc9bceb9
--- /dev/null
+++ b/arkguard/src/configs/IDataObfuscationOption.ts
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import type {EncryptType} from '../transformers/data/StringUnit';
+
+export interface IBooleanOption {
+ readonly mEnable: boolean;
+
+ readonly mThreshold: number;
+
+ /**
+ * skip obfuscation in loop for performance
+ */
+ readonly mSkipLoop: boolean;
+}
+
+export interface INumberOption {
+ readonly mEnable: boolean;
+
+ readonly mThreshold: number;
+
+ /**
+ * skip obfuscation in loop for performance
+ */
+ readonly mSkipLoop: boolean;
+}
+
+export interface IStringOption {
+
+ readonly mEnable: boolean;
+
+ readonly mThreshold: number;
+
+ /**
+ * skip obfuscation in loop for performance
+ */
+ readonly mSkipLoop: boolean;
+
+ readonly mSkipProperty: boolean;
+
+ readonly mSplitString: boolean;
+
+ readonly mStringArray: boolean;
+
+ readonly mStringArrayThreshold: number;
+
+ readonly mEncryptType: EncryptType;
+
+ readonly mStringArrayShuffle: boolean;
+
+ readonly mStringArrayCallsTransform: boolean;
+
+ readonly mStringArrayCallsThreshold: number;
+
+ mReservedStrings: string[];
+
+ readonly mObfuscationString: string[];
+}
+
+export interface IDataObfuscationOption {
+
+ readonly mEnable: boolean;
+
+ readonly mNumberOption: INumberOption;
+
+ readonly mStringOption: IStringOption;
+
+ readonly mBooleanOption: IBooleanOption;
+}
diff --git a/arkguard/src/configs/IHideOhApiOption.ts b/arkguard/src/configs/IHideOhApiOption.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ef4ee5389b45971d394c1290b77d639a64c0e0fd
--- /dev/null
+++ b/arkguard/src/configs/IHideOhApiOption.ts
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+export interface IHideOhApiOption {
+ readonly mEnable: boolean;
+
+ /**
+ * openHarmony api list to be hidden, like:
+ * - @ohos.hilog.info
+ */
+ readonly mProtectedApi: string[];
+}
diff --git a/arkguard/src/configs/IInstructionObfuscationOption.ts b/arkguard/src/configs/IInstructionObfuscationOption.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e6e6fd458b9097ebe7dfbf22044377e10327b220
--- /dev/null
+++ b/arkguard/src/configs/IInstructionObfuscationOption.ts
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+export enum InstructionObfsMethod {
+ /**
+ * use simple deformation to instruction
+ */
+ SIMPLE_DEFORM = 1,
+
+ /**
+ * transform instruction to MBA expression
+ */
+ MBA_EXPRESSION = 2,
+}
+
+export interface IInstructionObfuscationOption {
+ readonly mEnable: boolean;
+
+ readonly mThreshold: number;
+
+ /**
+ * skip obfuscation in loop for performance
+ */
+ readonly mSkipLoop: boolean;
+
+ readonly mInstructionObfsMethod: InstructionObfsMethod;
+}
diff --git a/arkguard/src/configs/INameObfuscationOption.ts b/arkguard/src/configs/INameObfuscationOption.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6279264c1ed642dfd18cd269275707b199f76d10
--- /dev/null
+++ b/arkguard/src/configs/INameObfuscationOption.ts
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import type {NameGeneratorType} from '../generator/NameFactory';
+
+export interface INameObfuscationOption {
+
+ readonly mEnable: boolean;
+
+ readonly mNameGeneratorType: NameGeneratorType;
+
+ readonly mRenameProperties: boolean;
+
+ readonly mReservedNames: string[];
+
+ mReservedProperties: string[];
+
+ readonly mDictionaryList?: string[];
+}
diff --git a/arkguard/src/configs/IOptions.ts b/arkguard/src/configs/IOptions.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4319bd3c25c9dbdef15e8fbe4270a3a862b2c163
--- /dev/null
+++ b/arkguard/src/configs/IOptions.ts
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import type {IControlFlowFatteningOption} from './IControlFlowFatteningOption';
+import type {IDataObfuscationOption} from './IDataObfuscationOption';
+import type {IBogusControlFlowOption} from './IBogusControlFlowOption';
+import type {INameObfuscationOption} from './INameObfuscationOption';
+import type {IInstructionObfuscationOption} from './IInstructionObfuscationOption';
+import type {IHideOhApiOption} from './IHideOhApiOption';
+
+export interface IOptions {
+ // Whether to generate compact code
+ readonly mCompact?: boolean;
+
+ // Whether to remove comments;
+ readonly mRemoveComments?: boolean;
+
+ // Whether to disable console output
+ readonly mDisableConsole?: boolean;
+
+ // whether to disable hilog output
+ readonly mDisableHilog?: boolean;
+
+ // Whether to do code simplification, includes variable declarations merging, expression merging...
+ readonly mSimplify?: boolean;
+
+ // whether to hide openHarmony api
+ readonly mHideOhApi?: IHideOhApiOption;
+
+ // Whether to do Name Obfuscation
+ readonly mNameObfuscation?: INameObfuscationOption;
+
+ // Whether to insert bogus control flow.
+ readonly mBogusControlFlow?: IBogusControlFlowOption;
+
+ // Whether to do control flow flattening
+ readonly mControlFlowFlattening?: IControlFlowFatteningOption;
+
+ // Whether to do data obfuscation
+ readonly mDataObfuscation?: IDataObfuscationOption;
+
+ // Whether to do Instruction obfuscation, includes obfuscating binary expression, logical expression, call expression.
+ readonly mInstructionObfuscation?: IInstructionObfuscationOption;
+
+ mNarrowFunctionNames?: Array;
+
+ mOutputDir?: string;
+
+ readonly mOhSdkPath?: string;
+
+ readonly mTopLevel?: boolean;
+
+ readonly mEnableSourceMap?: boolean;
+
+ readonly mEnableNameCache?: boolean;
+
+ readonly apiSavedDir?: string;
+
+ readonly applyReservedNamePath?: string;
+}
diff --git a/arkguard/src/configs/preset/ConfusionTables.ts b/arkguard/src/configs/preset/ConfusionTables.ts
new file mode 100644
index 0000000000000000000000000000000000000000..55c907bfb29ae81663241b7628d06ea514be26f3
--- /dev/null
+++ b/arkguard/src/configs/preset/ConfusionTables.ts
@@ -0,0 +1,1992 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+export let table: Object = {
+ '-': [
+ '\u{06d4}',
+ '\u{2cba}',
+ '\u{fe58}',
+ '\u{02d7}',
+ '\u{2212}',
+ '\u{2796}',
+ '\u{2011}',
+ '\u{2043}',
+ '\u{2012}',
+ '\u{2013}',
+ '\u{2010}'
+ ],
+ '.': [
+ '\u{0701}',
+ '\u{0660}',
+ '\u{2024}',
+ '\u{06f0}',
+ '\u{a60e}',
+ '\u{a4f8}',
+ '\u{0702}',
+ '\u{10a50}',
+ '\u{ff0e}',
+ '\u{1d16d}'
+ ],
+ '0': [
+ '\u{1d476}',
+ '\u{0585}',
+ '\u{004f}',
+ '\u{fbaa}',
+ '\u{1d4aa}',
+ '\u{06be}',
+ '\u{1d70e}',
+ '\u{09e6}',
+ '\u{0d02}',
+ '\u{1d4de}',
+ '\u{fee9}',
+ '\u{1d630}',
+ '\u{06c1}',
+ '\u{1ee24}',
+ '\u{1d45c}',
+ '\u{0a66}',
+ '\u{1d7bc}',
+ '\u{0c02}',
+ '\u{10ff}',
+ '\u{1d490}',
+ '\u{1d5c8}',
+ '\u{0d82}',
+ '\u{ff4f}',
+ '\u{1d744}',
+ '\u{0d20}',
+ '\u{1d5fc}',
+ '\u{fba6}',
+ '\u{0c66}',
+ '\u{102ab}',
+ '\u{1d11}',
+ '\u{0665}',
+ '\u{fbab}',
+ '\u{1d6d0}',
+ '\u{1d7b8}',
+ '\u{118c8}',
+ '\u{104c2}',
+ '\u{1d546}',
+ '\u{ff10}',
+ '\u{1d442}',
+ '\u{039f}',
+ '\u{10292}',
+ '\u{1d79e}',
+ '\u{feec}',
+ '\u{1d7ce}',
+ '\u{1d782}',
+ '\u{1d6d4}',
+ '\u{06f5}',
+ '\u{fbad}',
+ '\u{a4f3}',
+ '\u{feeb}',
+ '\u{1ee64}',
+ '\u{118e0}',
+ '\u{10404}',
+ '\u{2d54}',
+ '\u{1d7ec}',
+ '\u{feea}',
+ '\u{3007}',
+ '\u{1040}',
+ '\u{fba7}',
+ '\u{1d77e}',
+ '\u{1d428}',
+ '\u{0ae6}',
+ '\u{118b5}',
+ '\u{1d698}',
+ '\u{104ea}',
+ '\u{0ed0}',
+ '\u{05e1}',
+ '\u{1d4f8}',
+ '\u{0647}',
+ '\u{0c82}',
+ '\u{0966}',
+ '\u{0d66}',
+ '\u{1d7e2}',
+ '\u{118d7}',
+ '\u{1d64a}',
+ '\u{fbac}',
+ '\u{1d764}',
+ '\u{1042c}',
+ '\u{1d748}',
+ '\u{2134}',
+ '\u{1d67e}',
+ '\u{0b66}',
+ '\u{041e}',
+ '\u{ab3d}',
+ '\u{1ee84}',
+ '\u{1d6f0}',
+ '\u{1fbf0}',
+ '\u{0ce6}',
+ '\u{114d0}',
+ '\u{1d7d8}',
+ '\u{06d5}',
+ '\u{1d70a}',
+ '\u{1d40e}',
+ '\u{0b20}',
+ '\u{0e50}',
+ '\u{1d52c}',
+ '\u{1d594}',
+ '\u{1d616}',
+ '\u{1d5ae}',
+ '\u{03c3}',
+ '\u{043e}',
+ '\u{12d0}',
+ '\u{1d57a}',
+ '\u{1d72a}',
+ '\u{1d0f}',
+ '\u{006f}',
+ '\u{03bf}',
+ '\u{2c9e}',
+ '\u{1d560}',
+ '\u{0555}',
+ '\u{1d5e2}',
+ '\u{10516}',
+ '\u{0be6}',
+ '\u{07c0}',
+ '\u{1d6b6}',
+ '\u{1d664}',
+ '\u{ff2f}',
+ '\u{1d512}',
+ '\u{fba8}',
+ '\u{fba9}',
+ '\u{1d7f6}',
+ '\u{2c9f}',
+ '\u{101d}'
+ ],
+ '1': [
+ '\u{1d55d}',
+ '\u{0049}',
+ '\u{1d574}',
+ '\u{1d43c}',
+ '\u{0196}',
+ '\u{2d4f}',
+ '\u{1ee00}',
+ '\u{a4f2}',
+ '\u{fe8d}',
+ '\u{ff4c}',
+ '\u{1d661}',
+ '\u{2223}',
+ '\u{1d6b0}',
+ '\u{0406}',
+ '\u{2c92}',
+ '\u{05c0}',
+ '\u{1d7ed}',
+ '\u{1d6ea}',
+ '\u{ff11}',
+ '\u{1d610}',
+ '\u{05df}',
+ '\u{007c}',
+ '\u{1d5c5}',
+ '\u{1d695}',
+ '\u{ffe8}',
+ '\u{0661}',
+ '\u{1d408}',
+ '\u{1d540}',
+ '\u{05d5}',
+ '\u{1d7e3}',
+ '\u{1d678}',
+ '\u{16f28}',
+ '\u{1d5f9}',
+ '\u{1d4c1}',
+ '\u{1d7f7}',
+ '\u{1d724}',
+ '\u{1d4f5}',
+ '\u{217c}',
+ '\u{006c}',
+ '\u{1d7cf}',
+ '\u{1d5a8}',
+ '\u{1d425}',
+ '\u{04c0}',
+ '\u{10309}',
+ '\u{1d5dc}',
+ '\u{10320}',
+ '\u{1d459}',
+ '\u{1e8c7}',
+ '\u{23fd}',
+ '\u{0399}',
+ '\u{01c0}',
+ '\u{1d529}',
+ '\u{1d470}',
+ '\u{1d62d}',
+ '\u{07ca}',
+ '\u{ff29}',
+ '\u{2111}',
+ '\u{2160}',
+ '\u{fe8e}',
+ '\u{1ee80}',
+ '\u{2113}',
+ '\u{1028a}',
+ '\u{1d75e}',
+ '\u{2110}',
+ '\u{1d798}',
+ '\u{1fbf1}',
+ '\u{1d4d8}',
+ '\u{06f1}',
+ '\u{1d48d}',
+ '\u{1d7d9}',
+ '\u{1d644}',
+ '\u{0627}',
+ '\u{1d591}',
+ '\u{16c1}'
+ ],
+ '2': [
+ '\u{a75a}',
+ '\u{14bf}',
+ '\u{03e8}',
+ '\u{1d7ee}',
+ '\u{a6ef}',
+ '\u{01a7}',
+ '\u{1d7da}',
+ '\u{1d7e4}',
+ '\u{1fbf2}',
+ '\u{1d7d0}',
+ '\u{ff12}',
+ '\u{a644}',
+ '\u{1d7f8}'
+ ],
+ '3': [
+ '\u{1d7e5}',
+ '\u{a76a}',
+ '\u{1d7f9}',
+ '\u{021c}',
+ '\u{1d206}',
+ '\u{2ccc}',
+ '\u{0417}',
+ '\u{04e0}',
+ '\u{1d7ef}',
+ '\u{01b7}',
+ '\u{ff13}',
+ '\u{1fbf3}',
+ '\u{1d7db}',
+ '\u{1d7d1}',
+ '\u{16f3b}',
+ '\u{118ca}',
+ '\u{a7ab}'
+ ],
+ '4': [
+ '\u{1d7dc}',
+ '\u{1fbf4}',
+ '\u{1d7d2}',
+ '\u{1d7f0}',
+ '\u{118af}',
+ '\u{1d7e6}',
+ '\u{ff14}',
+ '\u{13ce}',
+ '\u{1d7fa}'
+ ],
+ '5': [
+ '\u{1d7f1}',
+ '\u{01bc}',
+ '\u{118bb}',
+ '\u{1fbf5}',
+ '\u{1d7d3}',
+ '\u{ff15}',
+ '\u{1d7fb}',
+ '\u{1d7e7}',
+ '\u{1d7dd}'
+ ],
+ '6': [
+ '\u{1d7f2}',
+ '\u{1d7e8}',
+ '\u{ff16}',
+ '\u{1fbf6}',
+ '\u{1d7d4}',
+ '\u{118d5}',
+ '\u{2cd2}',
+ '\u{0431}',
+ '\u{13ee}',
+ '\u{1d7de}',
+ '\u{1d7fc}'
+ ],
+ '7': [
+ '\u{1d7df}',
+ '\u{104d2}',
+ '\u{ff17}',
+ '\u{118c6}',
+ '\u{1fbf7}',
+ '\u{1d7f3}',
+ '\u{1d7e9}',
+ '\u{1d212}',
+ '\u{1d7d5}',
+ '\u{1d7fd}'
+ ],
+ '8': [
+ '\u{1d7d6}',
+ '\u{1d7fe}',
+ '\u{0b03}',
+ '\u{1e8cb}',
+ '\u{0222}',
+ '\u{09ea}',
+ '\u{0a6a}',
+ '\u{1d7f4}',
+ '\u{0223}',
+ '\u{ff18}',
+ '\u{1031a}',
+ '\u{1d7e0}',
+ '\u{1fbf8}',
+ '\u{1d7ea}'
+ ],
+ '9': [
+ '\u{1d7ff}',
+ '\u{1fbf9}',
+ '\u{a76e}',
+ '\u{118ac}',
+ '\u{0a67}',
+ '\u{1d7d7}',
+ '\u{118d6}',
+ '\u{ff19}',
+ '\u{1d7e1}',
+ '\u{1d7eb}',
+ '\u{09ed}',
+ '\u{118cc}',
+ '\u{0d6d}',
+ '\u{2cca}',
+ '\u{0b68}',
+ '\u{1d7f5}'
+ ],
+ 'A': [
+ '\u{1d6e2}',
+ '\u{1d4d0}',
+ '\u{1d608}',
+ '\u{a4ee}',
+ '\u{1d71c}',
+ '\u{1d49c}',
+ '\u{1d504}',
+ '\u{ab7a}',
+ '\u{1d6a8}',
+ '\u{1d5d4}',
+ '\u{1d538}',
+ '\u{1d63c}',
+ '\u{1d56c}',
+ '\u{1d670}',
+ '\u{0391}',
+ '\u{1d434}',
+ '\u{16f40}',
+ '\u{0410}',
+ '\u{15c5}',
+ '\u{1d00}',
+ '\u{1d400}',
+ '\u{ff21}',
+ '\u{1d756}',
+ '\u{102a0}',
+ '\u{13aa}',
+ '\u{1d5a0}',
+ '\u{1d468}',
+ '\u{1d790}'
+ ],
+ 'B': [
+ '\u{1d539}',
+ '\u{1d4d1}',
+ '\u{1d671}',
+ '\u{0412}',
+ '\u{1d5d5}',
+ '\u{a7b4}',
+ '\u{1d791}',
+ '\u{1d56d}',
+ '\u{1d757}',
+ '\u{10282}',
+ '\u{102a1}',
+ '\u{0432}',
+ '\u{1d6e3}',
+ '\u{0392}',
+ '\u{1d6a9}',
+ '\u{13f4}',
+ '\u{15f7}',
+ '\u{16d2}',
+ '\u{10301}',
+ '\u{1d505}',
+ '\u{1d469}',
+ '\u{1d609}',
+ '\u{1d71d}',
+ '\u{1d401}',
+ '\u{212c}',
+ '\u{1d435}',
+ '\u{13fc}',
+ '\u{1d5a1}',
+ '\u{1d63d}',
+ '\u{a4d0}',
+ '\u{ff22}',
+ '\u{0299}'
+ ],
+ 'C': [
+ '\u{1d672}',
+ '\u{1d5a2}',
+ '\u{1d60a}',
+ '\u{1d436}',
+ '\u{118e9}',
+ '\u{10415}',
+ '\u{13df}',
+ '\u{118f2}',
+ '\u{212d}',
+ '\u{ff23}',
+ '\u{03f9}',
+ '\u{1d4d2}',
+ '\u{2ca4}',
+ '\u{1d63e}',
+ '\u{0421}',
+ '\u{1f74c}',
+ '\u{216d}',
+ '\u{1455}',
+ '\u{a4da}',
+ '\u{1d46a}',
+ '\u{1d49e}',
+ '\u{2282}',
+ '\u{2102}',
+ '\u{2e26}',
+ '\u{10302}',
+ '\u{1051c}',
+ '\u{1d402}',
+ '\u{1d56e}',
+ '\u{1d5d6}',
+ '\u{102a2}'
+ ],
+ 'D': [
+ '\u{1d507}',
+ '\u{1d63f}',
+ '\u{1d49f}',
+ '\u{1d673}',
+ '\u{a4d3}',
+ '\u{1d60b}',
+ '\u{2145}',
+ '\u{1d46b}',
+ '\u{1d5d7}',
+ '\u{1d53b}',
+ '\u{ab70}',
+ '\u{ff24}',
+ '\u{1d5a3}',
+ '\u{1d4d3}',
+ '\u{1d05}',
+ '\u{1d56f}',
+ '\u{216e}',
+ '\u{13a0}',
+ '\u{15ea}',
+ '\u{1d437}',
+ '\u{15de}',
+ '\u{1d403}'
+ ],
+ 'E': [
+ '\u{1d46c}',
+ '\u{1d6ac}',
+ '\u{1d53c}',
+ '\u{1d570}',
+ '\u{1d5d8}',
+ '\u{118a6}',
+ '\u{1d404}',
+ '\u{1d6e6}',
+ '\u{1d508}',
+ '\u{22ff}',
+ '\u{1d674}',
+ '\u{2130}',
+ '\u{13ac}',
+ '\u{a4f0}',
+ '\u{1d794}',
+ '\u{2d39}',
+ '\u{118ae}',
+ '\u{1d640}',
+ '\u{ff25}',
+ '\u{ab7c}',
+ '\u{1d4d4}',
+ '\u{1d438}',
+ '\u{1d5a4}',
+ '\u{0395}',
+ '\u{1d60c}',
+ '\u{1d720}',
+ '\u{0415}',
+ '\u{1d07}',
+ '\u{1d75a}',
+ '\u{10286}'
+ ],
+ 'F': [
+ '\u{1d571}',
+ '\u{2131}',
+ '\u{a798}',
+ '\u{1d405}',
+ '\u{a4dd}',
+ '\u{118c2}',
+ '\u{1d5a5}',
+ '\u{1d60d}',
+ '\u{118a2}',
+ '\u{15b4}',
+ '\u{1d675}',
+ '\u{1d5d9}',
+ '\u{1d46d}',
+ '\u{1d641}',
+ '\u{10287}',
+ '\u{10525}',
+ '\u{1d509}',
+ '\u{ff26}',
+ '\u{1d213}',
+ '\u{1d7ca}',
+ '\u{1d53d}',
+ '\u{1d4d5}',
+ '\u{1d439}',
+ '\u{102a5}',
+ '\u{03dc}'
+ ],
+ 'G': [
+ '\u{1d4a2}',
+ '\u{0262}',
+ '\u{13c0}',
+ '\u{a4d6}',
+ '\u{1d43a}',
+ '\u{1d53e}',
+ '\u{1d5da}',
+ '\u{050c}',
+ '\u{1d676}',
+ '\u{1d572}',
+ '\u{1d60e}',
+ '\u{1d4d6}',
+ '\u{13f3}',
+ '\u{1d642}',
+ '\u{1d5a6}',
+ '\u{1d46e}',
+ '\u{ab90}',
+ '\u{050d}',
+ '\u{1d50a}',
+ '\u{1d406}',
+ '\u{13fb}',
+ '\u{ff27}'
+ ],
+ 'H': [
+ '\u{210d}',
+ '\u{2c8e}',
+ '\u{ab8b}',
+ '\u{1d46f}',
+ '\u{ff28}',
+ '\u{041d}',
+ '\u{1d677}',
+ '\u{029c}',
+ '\u{1d6e8}',
+ '\u{1d43b}',
+ '\u{1d4d7}',
+ '\u{1d5db}',
+ '\u{1d573}',
+ '\u{a4e7}',
+ '\u{1d722}',
+ '\u{1d643}',
+ '\u{043d}',
+ '\u{1d5a7}',
+ '\u{0397}',
+ '\u{1d796}',
+ '\u{157c}',
+ '\u{1d407}',
+ '\u{102cf}',
+ '\u{210b}',
+ '\u{210c}',
+ '\u{13bb}',
+ '\u{1d6ae}',
+ '\u{1d60f}',
+ '\u{1d75c}'
+ ],
+ 'I': [
+ '\u{1d55d}',
+ '\u{1d574}',
+ '\u{0031}',
+ '\u{1d43c}',
+ '\u{0196}',
+ '\u{2d4f}',
+ '\u{1ee00}',
+ '\u{a4f2}',
+ '\u{fe8d}',
+ '\u{ff4c}',
+ '\u{1d661}',
+ '\u{2223}',
+ '\u{1d6b0}',
+ '\u{0406}',
+ '\u{2c92}',
+ '\u{05c0}',
+ '\u{1d7ed}',
+ '\u{1d6ea}',
+ '\u{ff11}',
+ '\u{1d610}',
+ '\u{05df}',
+ '\u{007c}',
+ '\u{1d5c5}',
+ '\u{1d695}',
+ '\u{ffe8}',
+ '\u{0661}',
+ '\u{1d408}',
+ '\u{1d540}',
+ '\u{05d5}',
+ '\u{1d7e3}',
+ '\u{1d678}',
+ '\u{16f28}',
+ '\u{1d5f9}',
+ '\u{1d4c1}',
+ '\u{1d7f7}',
+ '\u{1d724}',
+ '\u{1d4f5}',
+ '\u{217c}',
+ '\u{006c}',
+ '\u{1d7cf}',
+ '\u{1d5a8}',
+ '\u{1d425}',
+ '\u{04c0}',
+ '\u{10309}',
+ '\u{1d5dc}',
+ '\u{10320}',
+ '\u{1d459}',
+ '\u{1e8c7}',
+ '\u{23fd}',
+ '\u{0399}',
+ '\u{01c0}',
+ '\u{1d529}',
+ '\u{1d470}',
+ '\u{1d62d}',
+ '\u{07ca}',
+ '\u{ff29}',
+ '\u{2111}',
+ '\u{2160}',
+ '\u{fe8e}',
+ '\u{1ee80}',
+ '\u{2113}',
+ '\u{1028a}',
+ '\u{1d75e}',
+ '\u{2110}',
+ '\u{1d798}',
+ '\u{1fbf1}',
+ '\u{1d4d8}',
+ '\u{06f1}',
+ '\u{1d48d}',
+ '\u{1d7d9}',
+ '\u{1d644}',
+ '\u{0627}',
+ '\u{1d591}',
+ '\u{16c1}'
+ ],
+ 'J': [
+ '\u{0408}',
+ '\u{a7b2}',
+ '\u{1d645}',
+ '\u{1d50d}',
+ '\u{1d5a9}',
+ '\u{1d575}',
+ '\u{1d5dd}',
+ '\u{ab7b}',
+ '\u{1d409}',
+ '\u{1d0a}',
+ '\u{148d}',
+ '\u{ff2a}',
+ '\u{1d611}',
+ '\u{1d43d}',
+ '\u{1d679}',
+ '\u{a4d9}',
+ '\u{1d4a5}',
+ '\u{037f}',
+ '\u{1d541}',
+ '\u{1d471}',
+ '\u{1d4d9}',
+ '\u{13ab}'
+ ],
+ 'K': [
+ '\u{16d5}',
+ '\u{1d646}',
+ '\u{1d4a6}',
+ '\u{1d5aa}',
+ '\u{1d43e}',
+ '\u{039a}',
+ '\u{1d542}',
+ '\u{a4d7}',
+ '\u{1d4da}',
+ '\u{1d5de}',
+ '\u{1d612}',
+ '\u{1d6b1}',
+ '\u{10518}',
+ '\u{1d6eb}',
+ '\u{1d576}',
+ '\u{041a}',
+ '\u{1d75f}',
+ '\u{ff2b}',
+ '\u{13e6}',
+ '\u{1d799}',
+ '\u{1d50e}',
+ '\u{1d67a}',
+ '\u{1d472}',
+ '\u{1d40a}',
+ '\u{1d725}',
+ '\u{2c94}',
+ '\u{212a}'
+ ],
+ 'L': [
+ '\u{2cd1}',
+ '\u{1d647}',
+ '\u{1d43f}',
+ '\u{1d5ab}',
+ '\u{1d5df}',
+ '\u{abae}',
+ '\u{1d613}',
+ '\u{ff2c}',
+ '\u{1d473}',
+ '\u{1d50f}',
+ '\u{10526}',
+ '\u{1d577}',
+ '\u{1d67b}',
+ '\u{10443}',
+ '\u{a4e1}',
+ '\u{16f16}',
+ '\u{216c}',
+ '\u{14aa}',
+ '\u{2cd0}',
+ '\u{118a3}',
+ '\u{1d543}',
+ '\u{029f}',
+ '\u{1d40b}',
+ '\u{118b2}',
+ '\u{1d4db}',
+ '\u{2112}',
+ '\u{13de}',
+ '\u{1d22a}',
+ '\u{1041b}'
+ ],
+ 'M': [
+ '\u{102b0}',
+ '\u{1d4dc}',
+ '\u{216f}',
+ '\u{10311}',
+ '\u{15f0}',
+ '\u{1d5ac}',
+ '\u{16d6}',
+ '\u{1d614}',
+ '\u{039c}',
+ '\u{1d510}',
+ '\u{1d761}',
+ '\u{1d6b3}',
+ '\u{1d727}',
+ '\u{1d40c}',
+ '\u{1d474}',
+ '\u{1d67c}',
+ '\u{1d5e0}',
+ '\u{13b7}',
+ '\u{1d440}',
+ '\u{041c}',
+ '\u{2133}',
+ '\u{a4df}',
+ '\u{1d578}',
+ '\u{ff2d}',
+ '\u{1d79b}',
+ '\u{03fa}',
+ '\u{1d648}',
+ '\u{1d6ed}',
+ '\u{1d544}',
+ '\u{2c98}'
+ ],
+ 'N': [
+ '\u{1d441}',
+ '\u{1d762}',
+ '\u{2c9a}',
+ '\u{1d5ad}',
+ '\u{1d615}',
+ '\u{1d40d}',
+ '\u{0274}',
+ '\u{1d6b4}',
+ '\u{1d579}',
+ '\u{1d4a9}',
+ '\u{1d649}',
+ '\u{a4e0}',
+ '\u{1d728}',
+ '\u{2115}',
+ '\u{10513}',
+ '\u{1d5e1}',
+ '\u{1d4dd}',
+ '\u{1d79c}',
+ '\u{1d511}',
+ '\u{1d6ee}',
+ '\u{ff2e}',
+ '\u{1d475}',
+ '\u{1d67d}',
+ '\u{039d}'
+ ],
+ 'O': [
+ '\u{1d476}',
+ '\u{0585}',
+ '\u{fbaa}',
+ '\u{1d4aa}',
+ '\u{06be}',
+ '\u{1d70e}',
+ '\u{09e6}',
+ '\u{0d02}',
+ '\u{1d4de}',
+ '\u{fee9}',
+ '\u{1d630}',
+ '\u{06c1}',
+ '\u{1ee24}',
+ '\u{1d45c}',
+ '\u{0a66}',
+ '\u{1d7bc}',
+ '\u{0c02}',
+ '\u{10ff}',
+ '\u{1d490}',
+ '\u{1d5c8}',
+ '\u{0d82}',
+ '\u{ff4f}',
+ '\u{1d744}',
+ '\u{0d20}',
+ '\u{1d5fc}',
+ '\u{fba6}',
+ '\u{0c66}',
+ '\u{102ab}',
+ '\u{1d11}',
+ '\u{0665}',
+ '\u{fbab}',
+ '\u{1d6d0}',
+ '\u{1d7b8}',
+ '\u{118c8}',
+ '\u{0030}',
+ '\u{104c2}',
+ '\u{1d546}',
+ '\u{ff10}',
+ '\u{1d442}',
+ '\u{039f}',
+ '\u{10292}',
+ '\u{1d79e}',
+ '\u{feec}',
+ '\u{1d7ce}',
+ '\u{1d782}',
+ '\u{1d6d4}',
+ '\u{06f5}',
+ '\u{fbad}',
+ '\u{a4f3}',
+ '\u{feeb}',
+ '\u{1ee64}',
+ '\u{118e0}',
+ '\u{10404}',
+ '\u{2d54}',
+ '\u{1d7ec}',
+ '\u{feea}',
+ '\u{3007}',
+ '\u{1040}',
+ '\u{fba7}',
+ '\u{1d77e}',
+ '\u{1d428}',
+ '\u{0ae6}',
+ '\u{118b5}',
+ '\u{1d698}',
+ '\u{104ea}',
+ '\u{0ed0}',
+ '\u{05e1}',
+ '\u{1d4f8}',
+ '\u{0647}',
+ '\u{0c82}',
+ '\u{0966}',
+ '\u{0d66}',
+ '\u{1d7e2}',
+ '\u{118d7}',
+ '\u{1d64a}',
+ '\u{fbac}',
+ '\u{1d764}',
+ '\u{1042c}',
+ '\u{1d748}',
+ '\u{2134}',
+ '\u{1d67e}',
+ '\u{0b66}',
+ '\u{041e}',
+ '\u{ab3d}',
+ '\u{1ee84}',
+ '\u{1d6f0}',
+ '\u{1fbf0}',
+ '\u{0ce6}',
+ '\u{114d0}',
+ '\u{1d7d8}',
+ '\u{06d5}',
+ '\u{1d70a}',
+ '\u{1d40e}',
+ '\u{0b20}',
+ '\u{0e50}',
+ '\u{1d52c}',
+ '\u{1d594}',
+ '\u{1d616}',
+ '\u{1d5ae}',
+ '\u{03c3}',
+ '\u{043e}',
+ '\u{12d0}',
+ '\u{1d57a}',
+ '\u{1d72a}',
+ '\u{1d0f}',
+ '\u{006f}',
+ '\u{03bf}',
+ '\u{2c9e}',
+ '\u{1d560}',
+ '\u{0555}',
+ '\u{1d5e2}',
+ '\u{10516}',
+ '\u{0be6}',
+ '\u{07c0}',
+ '\u{1d6b6}',
+ '\u{1d664}',
+ '\u{ff2f}',
+ '\u{1d512}',
+ '\u{fba8}',
+ '\u{fba9}',
+ '\u{1d7f6}',
+ '\u{2c9f}',
+ '\u{101d}'
+ ],
+ 'P': [
+ '\u{abb2}',
+ '\u{1d5e3}',
+ '\u{1d29}',
+ '\u{1d4ab}',
+ '\u{ff30}',
+ '\u{1d64b}',
+ '\u{1d5af}',
+ '\u{1d513}',
+ '\u{0420}',
+ '\u{2119}',
+ '\u{1d67f}',
+ '\u{1d4df}',
+ '\u{a4d1}',
+ '\u{1d6b8}',
+ '\u{03a1}',
+ '\u{1d57b}',
+ '\u{1d766}',
+ '\u{1d7a0}',
+ '\u{10295}',
+ '\u{1d18}',
+ '\u{1d443}',
+ '\u{146d}',
+ '\u{1d40f}',
+ '\u{2ca2}',
+ '\u{1d6f2}',
+ '\u{1d617}',
+ '\u{13e2}',
+ '\u{1d72c}',
+ '\u{1d477}'
+ ],
+ 'Q': [
+ '\u{1d4ac}',
+ '\u{1d57c}',
+ '\u{2d55}',
+ '\u{1d478}',
+ '\u{1d444}',
+ '\u{1d410}',
+ '\u{211a}',
+ '\u{1d514}',
+ '\u{1d64c}',
+ '\u{ff31}',
+ '\u{1d618}',
+ '\u{1d5b0}',
+ '\u{1d680}',
+ '\u{1d5e4}',
+ '\u{1d4e0}'
+ ],
+ 'R': [
+ '\u{1d479}',
+ '\u{211c}',
+ '\u{ab71}',
+ '\u{1d216}',
+ '\u{1d5e5}',
+ '\u{1587}',
+ '\u{0280}',
+ '\u{1d5b1}',
+ '\u{1d411}',
+ '\u{16b1}',
+ '\u{01a6}',
+ '\u{13a1}',
+ '\u{ff32}',
+ '\u{211b}',
+ '\u{aba2}',
+ '\u{1d64d}',
+ '\u{13d2}',
+ '\u{104b4}',
+ '\u{1d57d}',
+ '\u{211d}',
+ '\u{1d445}',
+ '\u{1d681}',
+ '\u{16f35}',
+ '\u{1d4e1}',
+ '\u{a4e3}',
+ '\u{1d619}'
+ ],
+ 'S': [
+ '\u{054f}',
+ '\u{ff33}',
+ '\u{1d4e2}',
+ '\u{1d57e}',
+ '\u{1d5b2}',
+ '\u{10296}',
+ '\u{13da}',
+ '\u{1d47a}',
+ '\u{1d446}',
+ '\u{1d4ae}',
+ '\u{1d61a}',
+ '\u{1d64e}',
+ '\u{10420}',
+ '\u{13d5}',
+ '\u{1d5e6}',
+ '\u{a4e2}',
+ '\u{1d516}',
+ '\u{1d412}',
+ '\u{1d54a}',
+ '\u{16f3a}',
+ '\u{1d682}',
+ '\u{0405}'
+ ],
+ 'T': [
+ '\u{1d6d5}',
+ '\u{1d683}',
+ '\u{1d47b}',
+ '\u{1d54b}',
+ '\u{27d9}',
+ '\u{2ca6}',
+ '\u{16f0a}',
+ '\u{1d1b}',
+ '\u{1d413}',
+ '\u{10297}',
+ '\u{ab72}',
+ '\u{1d4e3}',
+ '\u{1d7bd}',
+ '\u{1d61b}',
+ '\u{03c4}',
+ '\u{1d6bb}',
+ '\u{1d783}',
+ '\u{22a4}',
+ '\u{0422}',
+ '\u{0442}',
+ '\u{1f768}',
+ '\u{1d5b3}',
+ '\u{1d769}',
+ '\u{1d6f5}',
+ '\u{1d4af}',
+ '\u{1d5e7}',
+ '\u{1d64f}',
+ '\u{03a4}',
+ '\u{102b1}',
+ '\u{1d517}',
+ '\u{ff34}',
+ '\u{1d7a3}',
+ '\u{1d749}',
+ '\u{1d447}',
+ '\u{1d70f}',
+ '\u{13a2}',
+ '\u{a4d4}',
+ '\u{1d72f}',
+ '\u{118bc}',
+ '\u{10315}',
+ '\u{1d57f}'
+ ],
+ 'U': [
+ '\u{1d448}',
+ '\u{1d414}',
+ '\u{22c3}',
+ '\u{222a}',
+ '\u{1d5b4}',
+ '\u{1d518}',
+ '\u{1d580}',
+ '\u{1d47c}',
+ '\u{1d4b0}',
+ '\u{1d650}',
+ '\u{144c}',
+ '\u{104ce}',
+ '\u{1d4e4}',
+ '\u{1d5e8}',
+ '\u{1d61c}',
+ '\u{1d684}',
+ '\u{118b8}',
+ '\u{16f42}',
+ '\u{a4f4}',
+ '\u{1d54c}',
+ '\u{1200}',
+ '\u{ff35}',
+ '\u{054d}'
+ ],
+ 'V': [
+ '\u{1d415}',
+ '\u{1d685}',
+ '\u{1051d}',
+ '\u{2164}',
+ '\u{1d581}',
+ '\u{13d9}',
+ '\u{142f}',
+ '\u{0474}',
+ '\u{a6df}',
+ '\u{2d38}',
+ '\u{06f7}',
+ '\u{ff36}',
+ '\u{1d20d}',
+ '\u{1d54d}',
+ '\u{1d449}',
+ '\u{1d61d}',
+ '\u{1d4b1}',
+ '\u{1d47d}',
+ '\u{1d5b5}',
+ '\u{118a0}',
+ '\u{a4e6}',
+ '\u{1d519}',
+ '\u{0667}',
+ '\u{1d4e5}',
+ '\u{1d5e9}',
+ '\u{16f08}',
+ '\u{1d651}'
+ ],
+ 'W': [
+ '\u{1d686}',
+ '\u{118e6}',
+ '\u{051c}',
+ '\u{1d652}',
+ '\u{1d47e}',
+ '\u{1d4b2}',
+ '\u{1d416}',
+ '\u{1d4e6}',
+ '\u{1d5ea}',
+ '\u{118ef}',
+ '\u{1d51a}',
+ '\u{13d4}',
+ '\u{1d5b6}',
+ '\u{ff37}',
+ '\u{1d54e}',
+ '\u{1d44a}',
+ '\u{1d582}',
+ '\u{13b3}',
+ '\u{a4ea}',
+ '\u{1d61e}'
+ ],
+ 'X': [
+ '\u{1d5b7}',
+ '\u{2169}',
+ '\u{1d7a6}',
+ '\u{1d4b3}',
+ '\u{10322}',
+ '\u{2573}',
+ '\u{1d61f}',
+ '\u{03a7}',
+ '\u{1d6be}',
+ '\u{10290}',
+ '\u{102b4}',
+ '\u{1d54f}',
+ '\u{10317}',
+ '\u{a4eb}',
+ '\u{2cac}',
+ '\u{1d47f}',
+ '\u{0425}',
+ '\u{ff38}',
+ '\u{1d51b}',
+ '\u{1d76c}',
+ '\u{1d44b}',
+ '\u{118ec}',
+ '\u{166d}',
+ '\u{1d417}',
+ '\u{1d732}',
+ '\u{2d5d}',
+ '\u{10527}',
+ '\u{1d583}',
+ '\u{1d653}',
+ '\u{1d5eb}',
+ '\u{1d687}',
+ '\u{1d6f8}',
+ '\u{a7b3}',
+ '\u{1d4e7}',
+ '\u{16b7}'
+ ],
+ 'Y': [
+ '\u{1d584}',
+ '\u{a4ec}',
+ '\u{03a5}',
+ '\u{1d4b4}',
+ '\u{1d688}',
+ '\u{1d480}',
+ '\u{102b2}',
+ '\u{1d620}',
+ '\u{1d550}',
+ '\u{1d76a}',
+ '\u{1d654}',
+ '\u{13bd}',
+ '\u{1d5ec}',
+ '\u{2ca8}',
+ '\u{1d6bc}',
+ '\u{13a9}',
+ '\u{1d7a4}',
+ '\u{1d730}',
+ '\u{1d418}',
+ '\u{0423}',
+ '\u{1d4e8}',
+ '\u{118a4}',
+ '\u{ff39}',
+ '\u{04ae}',
+ '\u{16f43}',
+ '\u{1d51c}',
+ '\u{03d2}',
+ '\u{1d44c}',
+ '\u{1d6f6}',
+ '\u{1d5b8}'
+ ],
+ 'Z': [
+ '\u{1d44d}',
+ '\u{102f5}',
+ '\u{1d6e7}',
+ '\u{1d689}',
+ '\u{ff3a}',
+ '\u{2124}',
+ '\u{0396}',
+ '\u{1d655}',
+ '\u{1d6ad}',
+ '\u{1d621}',
+ '\u{1d721}',
+ '\u{1d75b}',
+ '\u{1d481}',
+ '\u{1d585}',
+ '\u{1d419}',
+ '\u{a4dc}',
+ '\u{1d5b9}',
+ '\u{1d4e9}',
+ '\u{13c3}',
+ '\u{1d795}',
+ '\u{1d4b5}',
+ '\u{1d5ed}',
+ '\u{118a9}',
+ '\u{118e5}',
+ '\u{2128}'
+ ],
+ 'a': [
+ '\u{ff41}',
+ '\u{0251}',
+ '\u{03b1}',
+ '\u{1d41a}',
+ '\u{1d656}',
+ '\u{1d770}',
+ '\u{1d482}',
+ '\u{1d68a}',
+ '\u{237a}',
+ '\u{1d7aa}',
+ '\u{1d4b6}',
+ '\u{0430}',
+ '\u{1d51e}',
+ '\u{1d5ee}',
+ '\u{1d622}',
+ '\u{1d552}',
+ '\u{1d5ba}',
+ '\u{1d44e}',
+ '\u{1d6fc}',
+ '\u{1d6c2}',
+ '\u{1d4ea}',
+ '\u{1d736}',
+ '\u{1d586}'
+ ],
+ 'b': [
+ '\u{1d483}',
+ '\u{1d41b}',
+ '\u{1d4b7}',
+ '\u{1d5bb}',
+ '\u{15af}',
+ '\u{1d587}',
+ '\u{1d623}',
+ '\u{13cf}',
+ '\u{1d4eb}',
+ '\u{0184}',
+ '\u{1d5ef}',
+ '\u{1d553}',
+ '\u{042c}',
+ '\u{1d51f}',
+ '\u{1d44f}',
+ '\u{ff42}',
+ '\u{1d68b}',
+ '\u{1d657}',
+ '\u{1472}'
+ ],
+ 'c': [
+ '\u{1d520}',
+ '\u{1d450}',
+ '\u{1d5f0}',
+ '\u{217d}',
+ '\u{1d588}',
+ '\u{1d04}',
+ '\u{1043d}',
+ '\u{abaf}',
+ '\u{1d4ec}',
+ '\u{1d624}',
+ '\u{1d41c}',
+ '\u{1d5bc}',
+ '\u{1d658}',
+ '\u{0441}',
+ '\u{1d554}',
+ '\u{03f2}',
+ '\u{2ca5}',
+ '\u{1d68c}',
+ '\u{1d484}',
+ '\u{1d4b8}',
+ '\u{ff43}'
+ ],
+ 'd': [
+ '\u{1d5f1}',
+ '\u{13e7}',
+ '\u{1d41d}',
+ '\u{1d4b9}',
+ '\u{2146}',
+ '\u{a4d2}',
+ '\u{0501}',
+ '\u{ff44}',
+ '\u{1d589}',
+ '\u{1d521}',
+ '\u{1d68d}',
+ '\u{1d659}',
+ '\u{1d5bd}',
+ '\u{146f}',
+ '\u{1d451}',
+ '\u{1d625}',
+ '\u{217e}',
+ '\u{1d555}',
+ '\u{1d485}',
+ '\u{1d4ed}'
+ ],
+ 'e': [
+ '\u{212f}',
+ '\u{1d522}',
+ '\u{04bd}',
+ '\u{ff45}',
+ '\u{1d556}',
+ '\u{2147}',
+ '\u{1d65a}',
+ '\u{212e}',
+ '\u{ab32}',
+ '\u{1d486}',
+ '\u{1d5f2}',
+ '\u{1d452}',
+ '\u{1d5be}',
+ '\u{1d4ee}',
+ '\u{1d58a}',
+ '\u{1d626}',
+ '\u{1d68e}',
+ '\u{0435}',
+ '\u{1d41e}'
+ ],
+ 'f': [
+ '\u{1d65b}',
+ '\u{1d487}',
+ '\u{017f}',
+ '\u{1d4bb}',
+ '\u{1d523}',
+ '\u{0584}',
+ '\u{1d7cb}',
+ '\u{1d5f3}',
+ '\u{ff46}',
+ '\u{1d68f}',
+ '\u{1d58b}',
+ '\u{ab35}',
+ '\u{1d4ef}',
+ '\u{1e9d}',
+ '\u{1d557}',
+ '\u{1d5bf}',
+ '\u{1d453}',
+ '\u{1d41f}',
+ '\u{03dd}',
+ '\u{1d627}',
+ '\u{a799}'
+ ],
+ 'g': [
+ '\u{1d58c}',
+ '\u{1d420}',
+ '\u{210a}',
+ '\u{1d5f4}',
+ '\u{1d558}',
+ '\u{1d65c}',
+ '\u{0261}',
+ '\u{1d524}',
+ '\u{1d690}',
+ '\u{018d}',
+ '\u{0581}',
+ '\u{1d5c0}',
+ '\u{1d628}',
+ '\u{ff47}',
+ '\u{1d488}',
+ '\u{1d83}',
+ '\u{1d4f0}',
+ '\u{1d454}'
+ ],
+ 'h': [
+ '\u{1d421}',
+ '\u{1d4bd}',
+ '\u{ff48}',
+ '\u{1d58d}',
+ '\u{1d65d}',
+ '\u{1d691}',
+ '\u{1d559}',
+ '\u{1d5c1}',
+ '\u{1d629}',
+ '\u{13c2}',
+ '\u{0570}',
+ '\u{1d5f5}',
+ '\u{1d4f1}',
+ '\u{210e}',
+ '\u{1d489}',
+ '\u{1d525}',
+ '\u{04bb}'
+ ],
+ 'i': [
+ '\u{1d62a}',
+ '\u{1fbe}',
+ '\u{2148}',
+ '\u{1d778}',
+ '\u{1d58e}',
+ '\u{1d422}',
+ '\u{04cf}',
+ '\u{037a}',
+ '\u{ff49}',
+ '\u{1d5c2}',
+ '\u{1d73e}',
+ '\u{a647}',
+ '\u{1d5f6}',
+ '\u{13a5}',
+ '\u{1d65e}',
+ '\u{118c3}',
+ '\u{0269}',
+ '\u{1d4be}',
+ '\u{1d6a4}',
+ '\u{2373}',
+ '\u{1d526}',
+ '\u{1d456}',
+ '\u{03b9}',
+ '\u{1d4f2}',
+ '\u{1d6ca}',
+ '\u{1d7b2}',
+ '\u{1d48a}',
+ '\u{1d692}',
+ '\u{026a}',
+ '\u{1d704}',
+ '\u{02db}',
+ '\u{ab75}',
+ '\u{0456}',
+ '\u{2170}',
+ '\u{2139}',
+ '\u{1d55a}',
+ '\u{0131}'
+ ],
+ 'j': [
+ '\u{1d423}',
+ '\u{1d5c3}',
+ '\u{1d693}',
+ '\u{2149}',
+ '\u{1d55b}',
+ '\u{03f3}',
+ '\u{ff4a}',
+ '\u{1d48b}',
+ '\u{1d457}',
+ '\u{1d4bf}',
+ '\u{1d65f}',
+ '\u{0458}',
+ '\u{1d527}',
+ '\u{1d62b}',
+ '\u{1d5f7}',
+ '\u{1d4f3}',
+ '\u{1d58f}'
+ ],
+ 'k': [
+ '\u{ff4b}',
+ '\u{1d55c}',
+ '\u{1d458}',
+ '\u{1d424}',
+ '\u{1d660}',
+ '\u{1d694}',
+ '\u{1d590}',
+ '\u{1d5c4}',
+ '\u{1d5f8}',
+ '\u{1d528}',
+ '\u{1d62c}',
+ '\u{1d48c}',
+ '\u{1d4f4}',
+ '\u{1d4c0}'
+ ],
+ 'l': [
+ '\u{1d55d}',
+ '\u{0049}',
+ '\u{1d574}',
+ '\u{0031}',
+ '\u{1d43c}',
+ '\u{0196}',
+ '\u{2d4f}',
+ '\u{1ee00}',
+ '\u{a4f2}',
+ '\u{fe8d}',
+ '\u{ff4c}',
+ '\u{1d661}',
+ '\u{2223}',
+ '\u{1d6b0}',
+ '\u{0406}',
+ '\u{2c92}',
+ '\u{05c0}',
+ '\u{1d7ed}',
+ '\u{1d6ea}',
+ '\u{ff11}',
+ '\u{1d610}',
+ '\u{05df}',
+ '\u{007c}',
+ '\u{1d5c5}',
+ '\u{1d695}',
+ '\u{ffe8}',
+ '\u{0661}',
+ '\u{1d408}',
+ '\u{1d540}',
+ '\u{05d5}',
+ '\u{1d7e3}',
+ '\u{1d678}',
+ '\u{16f28}',
+ '\u{1d5f9}',
+ '\u{1d4c1}',
+ '\u{1d7f7}',
+ '\u{1d724}',
+ '\u{1d4f5}',
+ '\u{217c}',
+ '\u{1d7cf}',
+ '\u{1d5a8}',
+ '\u{1d425}',
+ '\u{04c0}',
+ '\u{10309}',
+ '\u{1d5dc}',
+ '\u{10320}',
+ '\u{1d459}',
+ '\u{1e8c7}',
+ '\u{23fd}',
+ '\u{0399}',
+ '\u{01c0}',
+ '\u{1d529}',
+ '\u{1d470}',
+ '\u{1d62d}',
+ '\u{07ca}',
+ '\u{ff29}',
+ '\u{2111}',
+ '\u{2160}',
+ '\u{fe8e}',
+ '\u{1ee80}',
+ '\u{2113}',
+ '\u{1028a}',
+ '\u{1d75e}',
+ '\u{2110}',
+ '\u{1d798}',
+ '\u{1fbf1}',
+ '\u{1d4d8}',
+ '\u{06f1}',
+ '\u{1d48d}',
+ '\u{1d7d9}',
+ '\u{1d644}',
+ '\u{0627}',
+ '\u{1d591}',
+ '\u{16c1}'
+ ],
+ 'm': [
+ '\u{ff4d}'
+ ],
+ 'n': [
+ '\u{1d52b}',
+ '\u{1d593}',
+ '\u{1d5c7}',
+ '\u{1d45b}',
+ '\u{ff4e}',
+ '\u{1d5fb}',
+ '\u{0578}',
+ '\u{1d62f}',
+ '\u{1d4f7}',
+ '\u{1d663}',
+ '\u{1d48f}',
+ '\u{1d4c3}',
+ '\u{1d55f}',
+ '\u{1d697}',
+ '\u{1d427}',
+ '\u{057c}'
+ ],
+ 'o': [
+ '\u{1d476}',
+ '\u{0585}',
+ '\u{004f}',
+ '\u{fbaa}',
+ '\u{1d4aa}',
+ '\u{06be}',
+ '\u{1d70e}',
+ '\u{09e6}',
+ '\u{0d02}',
+ '\u{1d4de}',
+ '\u{fee9}',
+ '\u{1d630}',
+ '\u{06c1}',
+ '\u{1ee24}',
+ '\u{1d45c}',
+ '\u{0a66}',
+ '\u{1d7bc}',
+ '\u{0c02}',
+ '\u{10ff}',
+ '\u{1d490}',
+ '\u{1d5c8}',
+ '\u{0d82}',
+ '\u{ff4f}',
+ '\u{1d744}',
+ '\u{0d20}',
+ '\u{1d5fc}',
+ '\u{fba6}',
+ '\u{0c66}',
+ '\u{102ab}',
+ '\u{1d11}',
+ '\u{0665}',
+ '\u{fbab}',
+ '\u{1d6d0}',
+ '\u{1d7b8}',
+ '\u{118c8}',
+ '\u{0030}',
+ '\u{104c2}',
+ '\u{1d546}',
+ '\u{ff10}',
+ '\u{1d442}',
+ '\u{039f}',
+ '\u{10292}',
+ '\u{1d79e}',
+ '\u{feec}',
+ '\u{1d7ce}',
+ '\u{1d782}',
+ '\u{1d6d4}',
+ '\u{06f5}',
+ '\u{fbad}',
+ '\u{a4f3}',
+ '\u{feeb}',
+ '\u{1ee64}',
+ '\u{118e0}',
+ '\u{10404}',
+ '\u{2d54}',
+ '\u{1d7ec}',
+ '\u{feea}',
+ '\u{3007}',
+ '\u{1040}',
+ '\u{fba7}',
+ '\u{1d77e}',
+ '\u{1d428}',
+ '\u{0ae6}',
+ '\u{118b5}',
+ '\u{1d698}',
+ '\u{104ea}',
+ '\u{0ed0}',
+ '\u{05e1}',
+ '\u{1d4f8}',
+ '\u{0647}',
+ '\u{0c82}',
+ '\u{0966}',
+ '\u{0d66}',
+ '\u{1d7e2}',
+ '\u{118d7}',
+ '\u{1d64a}',
+ '\u{fbac}',
+ '\u{1d764}',
+ '\u{1042c}',
+ '\u{1d748}',
+ '\u{2134}',
+ '\u{1d67e}',
+ '\u{0b66}',
+ '\u{041e}',
+ '\u{ab3d}',
+ '\u{1ee84}',
+ '\u{1d6f0}',
+ '\u{1fbf0}',
+ '\u{0ce6}',
+ '\u{114d0}',
+ '\u{1d7d8}',
+ '\u{06d5}',
+ '\u{1d70a}',
+ '\u{1d40e}',
+ '\u{0b20}',
+ '\u{0e50}',
+ '\u{1d52c}',
+ '\u{1d594}',
+ '\u{1d616}',
+ '\u{1d5ae}',
+ '\u{03c3}',
+ '\u{043e}',
+ '\u{12d0}',
+ '\u{1d57a}',
+ '\u{1d72a}',
+ '\u{1d0f}',
+ '\u{03bf}',
+ '\u{2c9e}',
+ '\u{1d560}',
+ '\u{0555}',
+ '\u{1d5e2}',
+ '\u{10516}',
+ '\u{0be6}',
+ '\u{07c0}',
+ '\u{1d6b6}',
+ '\u{1d664}',
+ '\u{ff2f}',
+ '\u{1d512}',
+ '\u{fba8}',
+ '\u{fba9}',
+ '\u{1d7f6}',
+ '\u{2c9f}',
+ '\u{101d}'
+ ],
+ 'p': [
+ '\u{1d45d}',
+ '\u{1d561}',
+ '\u{1d78e}',
+ '\u{03f1}',
+ '\u{1d7c8}',
+ '\u{1d70c}',
+ '\u{ff50}',
+ '\u{2ca3}',
+ '\u{1d4c5}',
+ '\u{1d7ba}',
+ '\u{1d491}',
+ '\u{1d595}',
+ '\u{1d746}',
+ '\u{1d429}',
+ '\u{1d71a}',
+ '\u{1d665}',
+ '\u{1d754}',
+ '\u{1d780}',
+ '\u{1d52d}',
+ '\u{1d699}',
+ '\u{03c1}',
+ '\u{2374}',
+ '\u{1d5c9}',
+ '\u{1d6e0}',
+ '\u{1d5fd}',
+ '\u{0440}',
+ '\u{1d631}',
+ '\u{1d6d2}',
+ '\u{1d4f9}'
+ ],
+ 'q': [
+ '\u{051b}',
+ '\u{ff51}',
+ '\u{1d4fa}',
+ '\u{1d5ca}',
+ '\u{1d52e}',
+ '\u{1d562}',
+ '\u{1d45e}',
+ '\u{1d5fe}',
+ '\u{1d666}',
+ '\u{1d596}',
+ '\u{1d69a}',
+ '\u{0563}',
+ '\u{1d492}',
+ '\u{1d632}',
+ '\u{1d42a}',
+ '\u{0566}',
+ '\u{1d4c6}'
+ ],
+ 'r': [
+ '\u{1d597}',
+ '\u{1d4fb}',
+ '\u{2c85}',
+ '\u{1d5cb}',
+ '\u{1d45f}',
+ '\u{ab47}',
+ '\u{1d69b}',
+ '\u{1d42b}',
+ '\u{1d667}',
+ '\u{0433}',
+ '\u{1d493}',
+ '\u{1d4c7}',
+ '\u{ab48}',
+ '\u{1d5ff}',
+ '\u{ff52}',
+ '\u{1d52f}',
+ '\u{1d26}',
+ '\u{1d563}',
+ '\u{ab81}',
+ '\u{1d633}'
+ ],
+ 's': [
+ '\u{1d69c}',
+ '\u{a731}',
+ '\u{abaa}',
+ '\u{1d600}',
+ '\u{01bd}',
+ '\u{0455}',
+ '\u{1d460}',
+ '\u{118c1}',
+ '\u{1d564}',
+ '\u{1d668}',
+ '\u{1d4fc}',
+ '\u{1d494}',
+ '\u{1d5cc}',
+ '\u{1d634}',
+ '\u{1d42c}',
+ '\u{10448}',
+ '\u{1d530}',
+ '\u{1d598}',
+ '\u{ff53}',
+ '\u{1d4c8}'
+ ],
+ 't': [
+ '\u{1d495}',
+ '\u{1d5cd}',
+ '\u{1d599}',
+ '\u{1d669}',
+ '\u{1d531}',
+ '\u{1d4fd}',
+ '\u{1d4c9}',
+ '\u{1d42d}',
+ '\u{1d601}',
+ '\u{1d461}',
+ '\u{1d69d}',
+ '\u{1d565}',
+ '\u{ff54}',
+ '\u{1d635}'
+ ],
+ 'u': [
+ '\u{1d462}',
+ '\u{104f6}',
+ '\u{1d5ce}',
+ '\u{1d6d6}',
+ '\u{1d1c}',
+ '\u{ff55}',
+ '\u{1d42e}',
+ '\u{1d59a}',
+ '\u{1d69e}',
+ '\u{1d710}',
+ '\u{1d602}',
+ '\u{1d636}',
+ '\u{1d496}',
+ '\u{1d532}',
+ '\u{1d66a}',
+ '\u{118d8}',
+ '\u{03c5}',
+ '\u{1d7be}',
+ '\u{1d4ca}',
+ '\u{1d4fe}',
+ '\u{1d566}',
+ '\u{057d}',
+ '\u{ab4e}',
+ '\u{ab52}',
+ '\u{a79f}',
+ '\u{1d784}',
+ '\u{028b}',
+ '\u{1d74a}'
+ ],
+ 'v': [
+ '\u{1d66b}',
+ '\u{1d4ff}',
+ '\u{0475}',
+ '\u{1d7b6}',
+ '\u{ff56}',
+ '\u{1d497}',
+ '\u{1d533}',
+ '\u{1d77c}',
+ '\u{1d603}',
+ '\u{1d69f}',
+ '\u{1d42f}',
+ '\u{1d20}',
+ '\u{1d4cb}',
+ '\u{1d59b}',
+ '\u{05d8}',
+ '\u{22c1}',
+ '\u{1d742}',
+ '\u{1d6ce}',
+ '\u{11706}',
+ '\u{03bd}',
+ '\u{1d708}',
+ '\u{1d463}',
+ '\u{2228}',
+ '\u{1d637}',
+ '\u{1d5cf}',
+ '\u{aba9}',
+ '\u{118c0}',
+ '\u{2174}',
+ '\u{1d567}'
+ ],
+ 'w': [
+ '\u{1d604}',
+ '\u{ff57}',
+ '\u{1d5d0}',
+ '\u{1d498}',
+ '\u{1d430}',
+ '\u{1170f}',
+ '\u{1d638}',
+ '\u{1d66c}',
+ '\u{1d59c}',
+ '\u{1d534}',
+ '\u{1d500}',
+ '\u{ab83}',
+ '\u{1d464}',
+ '\u{026f}',
+ '\u{1170a}',
+ '\u{0561}',
+ '\u{1d6a0}',
+ '\u{1d568}',
+ '\u{1d21}',
+ '\u{1d4cc}',
+ '\u{0461}',
+ '\u{1170e}',
+ '\u{051d}'
+ ],
+ 'x': [
+ '\u{1d431}',
+ '\u{1d465}',
+ '\u{2a2f}',
+ '\u{1d535}',
+ '\u{1d5d1}',
+ '\u{0445}',
+ '\u{157d}',
+ '\u{1d639}',
+ '\u{1d4cd}',
+ '\u{1d499}',
+ '\u{2179}',
+ '\u{292c}',
+ '\u{1d605}',
+ '\u{00d7}',
+ '\u{166e}',
+ '\u{1d6a1}',
+ '\u{ff58}',
+ '\u{1541}',
+ '\u{1d569}',
+ '\u{292b}',
+ '\u{1d59d}',
+ '\u{1d501}',
+ '\u{1d66d}'
+ ],
+ 'y': [
+ '\u{ab5a}',
+ '\u{1eff}',
+ '\u{0443}',
+ '\u{028f}',
+ '\u{1d606}',
+ '\u{213d}',
+ '\u{1d772}',
+ '\u{04af}',
+ '\u{10e7}',
+ '\u{1d56a}',
+ '\u{1d4ce}',
+ '\u{1d6c4}',
+ '\u{1d63a}',
+ '\u{ff59}',
+ '\u{1d66e}',
+ '\u{1d738}',
+ '\u{0263}',
+ '\u{1d7ac}',
+ '\u{1d502}',
+ '\u{1d466}',
+ '\u{1d6a2}',
+ '\u{03b3}',
+ '\u{1d536}',
+ '\u{1d8c}',
+ '\u{1d49a}',
+ '\u{118dc}',
+ '\u{1d432}',
+ '\u{1d59e}',
+ '\u{1d6fe}',
+ '\u{1d5d2}'
+ ],
+ 'z': [
+ '\u{1d49b}',
+ '\u{1d433}',
+ '\u{1d59f}',
+ '\u{1d63b}',
+ '\u{1d56b}',
+ '\u{1d607}',
+ '\u{1d537}',
+ '\u{1d22}',
+ '\u{1d4cf}',
+ '\u{ab93}',
+ '\u{1d467}',
+ '\u{1d66f}',
+ '\u{1d6a3}',
+ '\u{118c4}',
+ '\u{1d503}',
+ '\u{1d5d3}',
+ '\u{ff5a}'
+ ]
+};
diff --git a/arkguard/src/configs/preset/es6_reserved_properties.json b/arkguard/src/configs/preset/es6_reserved_properties.json
new file mode 100644
index 0000000000000000000000000000000000000000..cf3d2dd8710b6ce79148d5b14e82fa66990dc34a
--- /dev/null
+++ b/arkguard/src/configs/preset/es6_reserved_properties.json
@@ -0,0 +1,7884 @@
+[
+ "$&",
+ "$'",
+ "$*",
+ "$+",
+ "$1",
+ "$2",
+ "$3",
+ "$4",
+ "$5",
+ "$6",
+ "$7",
+ "$8",
+ "$9",
+ "$_",
+ "$`",
+ "$input",
+ "-moz-animation",
+ "-moz-animation-delay",
+ "-moz-animation-direction",
+ "-moz-animation-duration",
+ "-moz-animation-fill-mode",
+ "-moz-animation-iteration-count",
+ "-moz-animation-name",
+ "-moz-animation-play-state",
+ "-moz-animation-timing-function",
+ "-moz-appearance",
+ "-moz-backface-visibility",
+ "-moz-border-end",
+ "-moz-border-end-color",
+ "-moz-border-end-style",
+ "-moz-border-end-width",
+ "-moz-border-image",
+ "-moz-border-start",
+ "-moz-border-start-color",
+ "-moz-border-start-style",
+ "-moz-border-start-width",
+ "-moz-box-align",
+ "-moz-box-direction",
+ "-moz-box-flex",
+ "-moz-box-ordinal-group",
+ "-moz-box-orient",
+ "-moz-box-pack",
+ "-moz-box-sizing",
+ "-moz-float-edge",
+ "-moz-font-feature-settings",
+ "-moz-font-language-override",
+ "-moz-force-broken-image-icon",
+ "-moz-hyphens",
+ "-moz-image-region",
+ "-moz-margin-end",
+ "-moz-margin-start",
+ "-moz-orient",
+ "-moz-osx-font-smoothing",
+ "-moz-outline-radius",
+ "-moz-outline-radius-bottomleft",
+ "-moz-outline-radius-bottomright",
+ "-moz-outline-radius-topleft",
+ "-moz-outline-radius-topright",
+ "-moz-padding-end",
+ "-moz-padding-start",
+ "-moz-perspective",
+ "-moz-perspective-origin",
+ "-moz-tab-size",
+ "-moz-text-size-adjust",
+ "-moz-transform",
+ "-moz-transform-origin",
+ "-moz-transform-style",
+ "-moz-transition",
+ "-moz-transition-delay",
+ "-moz-transition-duration",
+ "-moz-transition-property",
+ "-moz-transition-timing-function",
+ "-moz-user-focus",
+ "-moz-user-input",
+ "-moz-user-modify",
+ "-moz-user-select",
+ "-moz-window-dragging",
+ "-webkit-align-content",
+ "-webkit-align-items",
+ "-webkit-align-self",
+ "-webkit-animation",
+ "-webkit-animation-delay",
+ "-webkit-animation-direction",
+ "-webkit-animation-duration",
+ "-webkit-animation-fill-mode",
+ "-webkit-animation-iteration-count",
+ "-webkit-animation-name",
+ "-webkit-animation-play-state",
+ "-webkit-animation-timing-function",
+ "-webkit-appearance",
+ "-webkit-backface-visibility",
+ "-webkit-background-clip",
+ "-webkit-background-origin",
+ "-webkit-background-size",
+ "-webkit-border-bottom-left-radius",
+ "-webkit-border-bottom-right-radius",
+ "-webkit-border-image",
+ "-webkit-border-radius",
+ "-webkit-border-top-left-radius",
+ "-webkit-border-top-right-radius",
+ "-webkit-box-align",
+ "-webkit-box-direction",
+ "-webkit-box-flex",
+ "-webkit-box-ordinal-group",
+ "-webkit-box-orient",
+ "-webkit-box-pack",
+ "-webkit-box-shadow",
+ "-webkit-box-sizing",
+ "-webkit-filter",
+ "-webkit-flex",
+ "-webkit-flex-basis",
+ "-webkit-flex-direction",
+ "-webkit-flex-flow",
+ "-webkit-flex-grow",
+ "-webkit-flex-shrink",
+ "-webkit-flex-wrap",
+ "-webkit-justify-content",
+ "-webkit-line-clamp",
+ "-webkit-mask",
+ "-webkit-mask-clip",
+ "-webkit-mask-composite",
+ "-webkit-mask-image",
+ "-webkit-mask-origin",
+ "-webkit-mask-position",
+ "-webkit-mask-position-x",
+ "-webkit-mask-position-y",
+ "-webkit-mask-repeat",
+ "-webkit-mask-size",
+ "-webkit-order",
+ "-webkit-perspective",
+ "-webkit-perspective-origin",
+ "-webkit-text-fill-color",
+ "-webkit-text-size-adjust",
+ "-webkit-text-stroke",
+ "-webkit-text-stroke-color",
+ "-webkit-text-stroke-width",
+ "-webkit-transform",
+ "-webkit-transform-origin",
+ "-webkit-transform-style",
+ "-webkit-transition",
+ "-webkit-transition-delay",
+ "-webkit-transition-duration",
+ "-webkit-transition-property",
+ "-webkit-transition-timing-function",
+ "-webkit-user-select",
+ "0",
+ "1",
+ "10",
+ "11",
+ "12",
+ "13",
+ "14",
+ "15",
+ "16",
+ "17",
+ "18",
+ "19",
+ "2",
+ "20",
+ "3",
+ "4",
+ "5",
+ "6",
+ "7",
+ "8",
+ "9",
+ "@@iterator",
+ "ABORT_ERR",
+ "ACTIVE",
+ "ACTIVE_ATTRIBUTES",
+ "ACTIVE_TEXTURE",
+ "ACTIVE_UNIFORMS",
+ "ACTIVE_UNIFORM_BLOCKS",
+ "ADDITION",
+ "ALIASED_LINE_WIDTH_RANGE",
+ "ALIASED_POINT_SIZE_RANGE",
+ "ALLOW_KEYBOARD_INPUT",
+ "ALLPASS",
+ "ALPHA",
+ "ALPHA_BITS",
+ "ALREADY_SIGNALED",
+ "ALT_MASK",
+ "ALWAYS",
+ "ANY_SAMPLES_PASSED",
+ "ANY_SAMPLES_PASSED_CONSERVATIVE",
+ "ANY_TYPE",
+ "ANY_UNORDERED_NODE_TYPE",
+ "ARRAY_BUFFER",
+ "ARRAY_BUFFER_BINDING",
+ "ATTACHED_SHADERS",
+ "ATTRIBUTE_NODE",
+ "AT_TARGET",
+ "AbortController",
+ "AbortSignal",
+ "AbsoluteOrientationSensor",
+ "AbstractRange",
+ "Accelerometer",
+ "AddSearchProvider",
+ "AggregateError",
+ "AnalyserNode",
+ "Animation",
+ "AnimationEffect",
+ "AnimationEvent",
+ "AnimationPlaybackEvent",
+ "AnimationTimeline",
+ "AnonXMLHttpRequest",
+ "Any",
+ "ApplicationCache",
+ "ApplicationCacheErrorEvent",
+ "Array",
+ "ArrayBuffer",
+ "ArrayType",
+ "Atomics",
+ "Attr",
+ "Audio",
+ "AudioBuffer",
+ "AudioBufferSourceNode",
+ "AudioContext",
+ "AudioDestinationNode",
+ "AudioListener",
+ "AudioNode",
+ "AudioParam",
+ "AudioParamMap",
+ "AudioProcessingEvent",
+ "AudioScheduledSourceNode",
+ "AudioStreamTrack",
+ "AudioWorklet",
+ "AudioWorkletNode",
+ "AuthenticatorAssertionResponse",
+ "AuthenticatorAttestationResponse",
+ "AuthenticatorResponse",
+ "AutocompleteErrorEvent",
+ "BACK",
+ "BAD_BOUNDARYPOINTS_ERR",
+ "BAD_REQUEST",
+ "BANDPASS",
+ "BLEND",
+ "BLEND_COLOR",
+ "BLEND_DST_ALPHA",
+ "BLEND_DST_RGB",
+ "BLEND_EQUATION",
+ "BLEND_EQUATION_ALPHA",
+ "BLEND_EQUATION_RGB",
+ "BLEND_SRC_ALPHA",
+ "BLEND_SRC_RGB",
+ "BLUE_BITS",
+ "BLUR",
+ "BOOL",
+ "BOOLEAN_TYPE",
+ "BOOL_VEC2",
+ "BOOL_VEC3",
+ "BOOL_VEC4",
+ "BOTH",
+ "BROWSER_DEFAULT_WEBGL",
+ "BUBBLING_PHASE",
+ "BUFFER_SIZE",
+ "BUFFER_USAGE",
+ "BYTE",
+ "BYTES_PER_ELEMENT",
+ "BackgroundFetchManager",
+ "BackgroundFetchRecord",
+ "BackgroundFetchRegistration",
+ "BarProp",
+ "BarcodeDetector",
+ "BaseAudioContext",
+ "BaseHref",
+ "BatteryManager",
+ "BeforeInstallPromptEvent",
+ "BeforeLoadEvent",
+ "BeforeUnloadEvent",
+ "BigInt",
+ "BigInt64Array",
+ "BigUint64Array",
+ "BiquadFilterNode",
+ "Blob",
+ "BlobEvent",
+ "Bluetooth",
+ "BluetoothCharacteristicProperties",
+ "BluetoothDevice",
+ "BluetoothRemoteGATTCharacteristic",
+ "BluetoothRemoteGATTDescriptor",
+ "BluetoothRemoteGATTServer",
+ "BluetoothRemoteGATTService",
+ "BluetoothUUID",
+ "Boolean",
+ "BroadcastChannel",
+ "ByteLengthQueuingStrategy",
+ "CAPTURING_PHASE",
+ "CCW",
+ "CDATASection",
+ "CDATA_SECTION_NODE",
+ "CHANGE",
+ "CHARSET_RULE",
+ "CHECKING",
+ "CLAMP_TO_EDGE",
+ "CLICK",
+ "CLOSED",
+ "CLOSING",
+ "COLOR",
+ "COLOR_ATTACHMENT0",
+ "COLOR_ATTACHMENT1",
+ "COLOR_ATTACHMENT10",
+ "COLOR_ATTACHMENT11",
+ "COLOR_ATTACHMENT12",
+ "COLOR_ATTACHMENT13",
+ "COLOR_ATTACHMENT14",
+ "COLOR_ATTACHMENT15",
+ "COLOR_ATTACHMENT2",
+ "COLOR_ATTACHMENT3",
+ "COLOR_ATTACHMENT4",
+ "COLOR_ATTACHMENT5",
+ "COLOR_ATTACHMENT6",
+ "COLOR_ATTACHMENT7",
+ "COLOR_ATTACHMENT8",
+ "COLOR_ATTACHMENT9",
+ "COLOR_BUFFER_BIT",
+ "COLOR_CLEAR_VALUE",
+ "COLOR_WRITEMASK",
+ "COMMENT_NODE",
+ "COMPARE_REF_TO_TEXTURE",
+ "COMPILE_STATUS",
+ "COMPRESSED_RGBA_S3TC_DXT1_EXT",
+ "COMPRESSED_RGBA_S3TC_DXT3_EXT",
+ "COMPRESSED_RGBA_S3TC_DXT5_EXT",
+ "COMPRESSED_RGB_S3TC_DXT1_EXT",
+ "COMPRESSED_TEXTURE_FORMATS",
+ "CONDITION_SATISFIED",
+ "CONFIGURATION_UNSUPPORTED",
+ "CONNECTING",
+ "CONSTANT_ALPHA",
+ "CONSTANT_COLOR",
+ "CONSTRAINT_ERR",
+ "CONTEXT_LOST_WEBGL",
+ "CONTROL_MASK",
+ "COPY_READ_BUFFER",
+ "COPY_READ_BUFFER_BINDING",
+ "COPY_WRITE_BUFFER",
+ "COPY_WRITE_BUFFER_BINDING",
+ "COUNTER_STYLE_RULE",
+ "CSS",
+ "CSS2Properties",
+ "CSSAnimation",
+ "CSSCharsetRule",
+ "CSSConditionRule",
+ "CSSCounterStyleRule",
+ "CSSFontFaceRule",
+ "CSSFontFeatureValuesRule",
+ "CSSGroupingRule",
+ "CSSImageValue",
+ "CSSImportRule",
+ "CSSKeyframeRule",
+ "CSSKeyframesRule",
+ "CSSKeywordValue",
+ "CSSMathInvert",
+ "CSSMathMax",
+ "CSSMathMin",
+ "CSSMathNegate",
+ "CSSMathProduct",
+ "CSSMathSum",
+ "CSSMathValue",
+ "CSSMatrixComponent",
+ "CSSMediaRule",
+ "CSSMozDocumentRule",
+ "CSSNameSpaceRule",
+ "CSSNamespaceRule",
+ "CSSNumericArray",
+ "CSSNumericValue",
+ "CSSPageRule",
+ "CSSPerspective",
+ "CSSPositionValue",
+ "CSSPrimitiveValue",
+ "CSSRotate",
+ "CSSRule",
+ "CSSRuleList",
+ "CSSScale",
+ "CSSSkew",
+ "CSSSkewX",
+ "CSSSkewY",
+ "CSSStyleDeclaration",
+ "CSSStyleRule",
+ "CSSStyleSheet",
+ "CSSStyleValue",
+ "CSSSupportsRule",
+ "CSSTransformComponent",
+ "CSSTransformValue",
+ "CSSTransition",
+ "CSSTranslate",
+ "CSSUnitValue",
+ "CSSUnknownRule",
+ "CSSUnparsedValue",
+ "CSSValue",
+ "CSSValueList",
+ "CSSVariableReferenceValue",
+ "CSSVariablesDeclaration",
+ "CSSVariablesRule",
+ "CSSViewportRule",
+ "CSS_ATTR",
+ "CSS_CM",
+ "CSS_COUNTER",
+ "CSS_CUSTOM",
+ "CSS_DEG",
+ "CSS_DIMENSION",
+ "CSS_EMS",
+ "CSS_EXS",
+ "CSS_FILTER_BLUR",
+ "CSS_FILTER_BRIGHTNESS",
+ "CSS_FILTER_CONTRAST",
+ "CSS_FILTER_CUSTOM",
+ "CSS_FILTER_DROP_SHADOW",
+ "CSS_FILTER_GRAYSCALE",
+ "CSS_FILTER_HUE_ROTATE",
+ "CSS_FILTER_INVERT",
+ "CSS_FILTER_OPACITY",
+ "CSS_FILTER_REFERENCE",
+ "CSS_FILTER_SATURATE",
+ "CSS_FILTER_SEPIA",
+ "CSS_GRAD",
+ "CSS_HZ",
+ "CSS_IDENT",
+ "CSS_IN",
+ "CSS_INHERIT",
+ "CSS_KHZ",
+ "CSS_MATRIX",
+ "CSS_MATRIX3D",
+ "CSS_MM",
+ "CSS_MS",
+ "CSS_NUMBER",
+ "CSS_PC",
+ "CSS_PERCENTAGE",
+ "CSS_PERSPECTIVE",
+ "CSS_PRIMITIVE_VALUE",
+ "CSS_PT",
+ "CSS_PX",
+ "CSS_RAD",
+ "CSS_RECT",
+ "CSS_RGBCOLOR",
+ "CSS_ROTATE",
+ "CSS_ROTATE3D",
+ "CSS_ROTATEX",
+ "CSS_ROTATEY",
+ "CSS_ROTATEZ",
+ "CSS_S",
+ "CSS_SCALE",
+ "CSS_SCALE3D",
+ "CSS_SCALEX",
+ "CSS_SCALEY",
+ "CSS_SCALEZ",
+ "CSS_SKEW",
+ "CSS_SKEWX",
+ "CSS_SKEWY",
+ "CSS_STRING",
+ "CSS_TRANSLATE",
+ "CSS_TRANSLATE3D",
+ "CSS_TRANSLATEX",
+ "CSS_TRANSLATEY",
+ "CSS_TRANSLATEZ",
+ "CSS_UNKNOWN",
+ "CSS_URI",
+ "CSS_VALUE_LIST",
+ "CSS_VH",
+ "CSS_VMAX",
+ "CSS_VMIN",
+ "CSS_VW",
+ "CULL_FACE",
+ "CULL_FACE_MODE",
+ "CURRENT_PROGRAM",
+ "CURRENT_QUERY",
+ "CURRENT_VERTEX_ATTRIB",
+ "CUSTOM",
+ "CW",
+ "Cache",
+ "CacheStorage",
+ "CanvasCaptureMediaStream",
+ "CanvasCaptureMediaStreamTrack",
+ "CanvasGradient",
+ "CanvasPattern",
+ "CanvasRenderingContext2D",
+ "CaretPosition",
+ "ChannelMergerNode",
+ "ChannelSplitterNode",
+ "CharacterData",
+ "ClientRect",
+ "ClientRectList",
+ "Clipboard",
+ "ClipboardEvent",
+ "ClipboardItem",
+ "CloseEvent",
+ "Collator",
+ "CommandEvent",
+ "Comment",
+ "CompileError",
+ "CompositionEvent",
+ "CompressionStream",
+ "Console",
+ "ConstantSourceNode",
+ "Controllers",
+ "ConvolverNode",
+ "CountQueuingStrategy",
+ "Counter",
+ "Credential",
+ "CredentialsContainer",
+ "Crypto",
+ "CryptoKey",
+ "CustomElementRegistry",
+ "CustomEvent",
+ "DATABASE_ERR",
+ "DATA_CLONE_ERR",
+ "DATA_ERR",
+ "DBLCLICK",
+ "DECR",
+ "DECR_WRAP",
+ "DELETE_STATUS",
+ "DEPTH",
+ "DEPTH24_STENCIL8",
+ "DEPTH32F_STENCIL8",
+ "DEPTH_ATTACHMENT",
+ "DEPTH_BITS",
+ "DEPTH_BUFFER_BIT",
+ "DEPTH_CLEAR_VALUE",
+ "DEPTH_COMPONENT",
+ "DEPTH_COMPONENT16",
+ "DEPTH_COMPONENT24",
+ "DEPTH_COMPONENT32F",
+ "DEPTH_FUNC",
+ "DEPTH_RANGE",
+ "DEPTH_STENCIL",
+ "DEPTH_STENCIL_ATTACHMENT",
+ "DEPTH_TEST",
+ "DEPTH_WRITEMASK",
+ "DEVICE_INELIGIBLE",
+ "DIRECTION_DOWN",
+ "DIRECTION_LEFT",
+ "DIRECTION_RIGHT",
+ "DIRECTION_UP",
+ "DISABLED",
+ "DISPATCH_REQUEST_ERR",
+ "DITHER",
+ "DOCUMENT_FRAGMENT_NODE",
+ "DOCUMENT_NODE",
+ "DOCUMENT_POSITION_CONTAINED_BY",
+ "DOCUMENT_POSITION_CONTAINS",
+ "DOCUMENT_POSITION_DISCONNECTED",
+ "DOCUMENT_POSITION_FOLLOWING",
+ "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC",
+ "DOCUMENT_POSITION_PRECEDING",
+ "DOCUMENT_TYPE_NODE",
+ "DOMCursor",
+ "DOMError",
+ "DOMException",
+ "DOMImplementation",
+ "DOMImplementationLS",
+ "DOMMatrix",
+ "DOMMatrixReadOnly",
+ "DOMParser",
+ "DOMPoint",
+ "DOMPointReadOnly",
+ "DOMQuad",
+ "DOMRect",
+ "DOMRectList",
+ "DOMRectReadOnly",
+ "DOMRequest",
+ "DOMSTRING_SIZE_ERR",
+ "DOMSettableTokenList",
+ "DOMStringList",
+ "DOMStringMap",
+ "DOMTokenList",
+ "DOMTransactionEvent",
+ "DOM_DELTA_LINE",
+ "DOM_DELTA_PAGE",
+ "DOM_DELTA_PIXEL",
+ "DOM_INPUT_METHOD_DROP",
+ "DOM_INPUT_METHOD_HANDWRITING",
+ "DOM_INPUT_METHOD_IME",
+ "DOM_INPUT_METHOD_KEYBOARD",
+ "DOM_INPUT_METHOD_MULTIMODAL",
+ "DOM_INPUT_METHOD_OPTION",
+ "DOM_INPUT_METHOD_PASTE",
+ "DOM_INPUT_METHOD_SCRIPT",
+ "DOM_INPUT_METHOD_UNKNOWN",
+ "DOM_INPUT_METHOD_VOICE",
+ "DOM_KEY_LOCATION_JOYSTICK",
+ "DOM_KEY_LOCATION_LEFT",
+ "DOM_KEY_LOCATION_MOBILE",
+ "DOM_KEY_LOCATION_NUMPAD",
+ "DOM_KEY_LOCATION_RIGHT",
+ "DOM_KEY_LOCATION_STANDARD",
+ "DOM_VK_0",
+ "DOM_VK_1",
+ "DOM_VK_2",
+ "DOM_VK_3",
+ "DOM_VK_4",
+ "DOM_VK_5",
+ "DOM_VK_6",
+ "DOM_VK_7",
+ "DOM_VK_8",
+ "DOM_VK_9",
+ "DOM_VK_A",
+ "DOM_VK_ACCEPT",
+ "DOM_VK_ADD",
+ "DOM_VK_ALT",
+ "DOM_VK_ALTGR",
+ "DOM_VK_AMPERSAND",
+ "DOM_VK_ASTERISK",
+ "DOM_VK_AT",
+ "DOM_VK_ATTN",
+ "DOM_VK_B",
+ "DOM_VK_BACKSPACE",
+ "DOM_VK_BACK_QUOTE",
+ "DOM_VK_BACK_SLASH",
+ "DOM_VK_BACK_SPACE",
+ "DOM_VK_C",
+ "DOM_VK_CANCEL",
+ "DOM_VK_CAPS_LOCK",
+ "DOM_VK_CIRCUMFLEX",
+ "DOM_VK_CLEAR",
+ "DOM_VK_CLOSE_BRACKET",
+ "DOM_VK_CLOSE_CURLY_BRACKET",
+ "DOM_VK_CLOSE_PAREN",
+ "DOM_VK_COLON",
+ "DOM_VK_COMMA",
+ "DOM_VK_CONTEXT_MENU",
+ "DOM_VK_CONTROL",
+ "DOM_VK_CONVERT",
+ "DOM_VK_CRSEL",
+ "DOM_VK_CTRL",
+ "DOM_VK_D",
+ "DOM_VK_DECIMAL",
+ "DOM_VK_DELETE",
+ "DOM_VK_DIVIDE",
+ "DOM_VK_DOLLAR",
+ "DOM_VK_DOUBLE_QUOTE",
+ "DOM_VK_DOWN",
+ "DOM_VK_E",
+ "DOM_VK_EISU",
+ "DOM_VK_END",
+ "DOM_VK_ENTER",
+ "DOM_VK_EQUALS",
+ "DOM_VK_EREOF",
+ "DOM_VK_ESCAPE",
+ "DOM_VK_EXCLAMATION",
+ "DOM_VK_EXECUTE",
+ "DOM_VK_EXSEL",
+ "DOM_VK_F",
+ "DOM_VK_F1",
+ "DOM_VK_F10",
+ "DOM_VK_F11",
+ "DOM_VK_F12",
+ "DOM_VK_F13",
+ "DOM_VK_F14",
+ "DOM_VK_F15",
+ "DOM_VK_F16",
+ "DOM_VK_F17",
+ "DOM_VK_F18",
+ "DOM_VK_F19",
+ "DOM_VK_F2",
+ "DOM_VK_F20",
+ "DOM_VK_F21",
+ "DOM_VK_F22",
+ "DOM_VK_F23",
+ "DOM_VK_F24",
+ "DOM_VK_F25",
+ "DOM_VK_F26",
+ "DOM_VK_F27",
+ "DOM_VK_F28",
+ "DOM_VK_F29",
+ "DOM_VK_F3",
+ "DOM_VK_F30",
+ "DOM_VK_F31",
+ "DOM_VK_F32",
+ "DOM_VK_F33",
+ "DOM_VK_F34",
+ "DOM_VK_F35",
+ "DOM_VK_F36",
+ "DOM_VK_F4",
+ "DOM_VK_F5",
+ "DOM_VK_F6",
+ "DOM_VK_F7",
+ "DOM_VK_F8",
+ "DOM_VK_F9",
+ "DOM_VK_FINAL",
+ "DOM_VK_FRONT",
+ "DOM_VK_G",
+ "DOM_VK_GREATER_THAN",
+ "DOM_VK_H",
+ "DOM_VK_HANGUL",
+ "DOM_VK_HANJA",
+ "DOM_VK_HASH",
+ "DOM_VK_HELP",
+ "DOM_VK_HK_TOGGLE",
+ "DOM_VK_HOME",
+ "DOM_VK_HYPHEN_MINUS",
+ "DOM_VK_I",
+ "DOM_VK_INSERT",
+ "DOM_VK_J",
+ "DOM_VK_JUNJA",
+ "DOM_VK_K",
+ "DOM_VK_KANA",
+ "DOM_VK_KANJI",
+ "DOM_VK_L",
+ "DOM_VK_LEFT",
+ "DOM_VK_LEFT_TAB",
+ "DOM_VK_LESS_THAN",
+ "DOM_VK_M",
+ "DOM_VK_META",
+ "DOM_VK_MODECHANGE",
+ "DOM_VK_MULTIPLY",
+ "DOM_VK_N",
+ "DOM_VK_NONCONVERT",
+ "DOM_VK_NUMPAD0",
+ "DOM_VK_NUMPAD1",
+ "DOM_VK_NUMPAD2",
+ "DOM_VK_NUMPAD3",
+ "DOM_VK_NUMPAD4",
+ "DOM_VK_NUMPAD5",
+ "DOM_VK_NUMPAD6",
+ "DOM_VK_NUMPAD7",
+ "DOM_VK_NUMPAD8",
+ "DOM_VK_NUMPAD9",
+ "DOM_VK_NUM_LOCK",
+ "DOM_VK_O",
+ "DOM_VK_OEM_1",
+ "DOM_VK_OEM_102",
+ "DOM_VK_OEM_2",
+ "DOM_VK_OEM_3",
+ "DOM_VK_OEM_4",
+ "DOM_VK_OEM_5",
+ "DOM_VK_OEM_6",
+ "DOM_VK_OEM_7",
+ "DOM_VK_OEM_8",
+ "DOM_VK_OEM_COMMA",
+ "DOM_VK_OEM_MINUS",
+ "DOM_VK_OEM_PERIOD",
+ "DOM_VK_OEM_PLUS",
+ "DOM_VK_OPEN_BRACKET",
+ "DOM_VK_OPEN_CURLY_BRACKET",
+ "DOM_VK_OPEN_PAREN",
+ "DOM_VK_P",
+ "DOM_VK_PA1",
+ "DOM_VK_PAGEDOWN",
+ "DOM_VK_PAGEUP",
+ "DOM_VK_PAGE_DOWN",
+ "DOM_VK_PAGE_UP",
+ "DOM_VK_PAUSE",
+ "DOM_VK_PERCENT",
+ "DOM_VK_PERIOD",
+ "DOM_VK_PIPE",
+ "DOM_VK_PLAY",
+ "DOM_VK_PLUS",
+ "DOM_VK_PRINT",
+ "DOM_VK_PRINTSCREEN",
+ "DOM_VK_PROCESSKEY",
+ "DOM_VK_PROPERITES",
+ "DOM_VK_Q",
+ "DOM_VK_QUESTION_MARK",
+ "DOM_VK_QUOTE",
+ "DOM_VK_R",
+ "DOM_VK_REDO",
+ "DOM_VK_RETURN",
+ "DOM_VK_RIGHT",
+ "DOM_VK_S",
+ "DOM_VK_SCROLL_LOCK",
+ "DOM_VK_SELECT",
+ "DOM_VK_SEMICOLON",
+ "DOM_VK_SEPARATOR",
+ "DOM_VK_SHIFT",
+ "DOM_VK_SLASH",
+ "DOM_VK_SLEEP",
+ "DOM_VK_SPACE",
+ "DOM_VK_SUBTRACT",
+ "DOM_VK_T",
+ "DOM_VK_TAB",
+ "DOM_VK_TILDE",
+ "DOM_VK_U",
+ "DOM_VK_UNDERSCORE",
+ "DOM_VK_UNDO",
+ "DOM_VK_UNICODE",
+ "DOM_VK_UP",
+ "DOM_VK_V",
+ "DOM_VK_VOLUME_DOWN",
+ "DOM_VK_VOLUME_MUTE",
+ "DOM_VK_VOLUME_UP",
+ "DOM_VK_W",
+ "DOM_VK_WIN",
+ "DOM_VK_WINDOW",
+ "DOM_VK_WIN_ICO_00",
+ "DOM_VK_WIN_ICO_CLEAR",
+ "DOM_VK_WIN_ICO_HELP",
+ "DOM_VK_WIN_OEM_ATTN",
+ "DOM_VK_WIN_OEM_AUTO",
+ "DOM_VK_WIN_OEM_BACKTAB",
+ "DOM_VK_WIN_OEM_CLEAR",
+ "DOM_VK_WIN_OEM_COPY",
+ "DOM_VK_WIN_OEM_CUSEL",
+ "DOM_VK_WIN_OEM_ENLW",
+ "DOM_VK_WIN_OEM_FINISH",
+ "DOM_VK_WIN_OEM_FJ_JISHO",
+ "DOM_VK_WIN_OEM_FJ_LOYA",
+ "DOM_VK_WIN_OEM_FJ_MASSHOU",
+ "DOM_VK_WIN_OEM_FJ_ROYA",
+ "DOM_VK_WIN_OEM_FJ_TOUROKU",
+ "DOM_VK_WIN_OEM_JUMP",
+ "DOM_VK_WIN_OEM_PA1",
+ "DOM_VK_WIN_OEM_PA2",
+ "DOM_VK_WIN_OEM_PA3",
+ "DOM_VK_WIN_OEM_RESET",
+ "DOM_VK_WIN_OEM_WSCTRL",
+ "DOM_VK_X",
+ "DOM_VK_XF86XK_ADD_FAVORITE",
+ "DOM_VK_XF86XK_APPLICATION_LEFT",
+ "DOM_VK_XF86XK_APPLICATION_RIGHT",
+ "DOM_VK_XF86XK_AUDIO_CYCLE_TRACK",
+ "DOM_VK_XF86XK_AUDIO_FORWARD",
+ "DOM_VK_XF86XK_AUDIO_LOWER_VOLUME",
+ "DOM_VK_XF86XK_AUDIO_MEDIA",
+ "DOM_VK_XF86XK_AUDIO_MUTE",
+ "DOM_VK_XF86XK_AUDIO_NEXT",
+ "DOM_VK_XF86XK_AUDIO_PAUSE",
+ "DOM_VK_XF86XK_AUDIO_PLAY",
+ "DOM_VK_XF86XK_AUDIO_PREV",
+ "DOM_VK_XF86XK_AUDIO_RAISE_VOLUME",
+ "DOM_VK_XF86XK_AUDIO_RANDOM_PLAY",
+ "DOM_VK_XF86XK_AUDIO_RECORD",
+ "DOM_VK_XF86XK_AUDIO_REPEAT",
+ "DOM_VK_XF86XK_AUDIO_REWIND",
+ "DOM_VK_XF86XK_AUDIO_STOP",
+ "DOM_VK_XF86XK_AWAY",
+ "DOM_VK_XF86XK_BACK",
+ "DOM_VK_XF86XK_BACK_FORWARD",
+ "DOM_VK_XF86XK_BATTERY",
+ "DOM_VK_XF86XK_BLUE",
+ "DOM_VK_XF86XK_BLUETOOTH",
+ "DOM_VK_XF86XK_BOOK",
+ "DOM_VK_XF86XK_BRIGHTNESS_ADJUST",
+ "DOM_VK_XF86XK_CALCULATOR",
+ "DOM_VK_XF86XK_CALENDAR",
+ "DOM_VK_XF86XK_CD",
+ "DOM_VK_XF86XK_CLOSE",
+ "DOM_VK_XF86XK_COMMUNITY",
+ "DOM_VK_XF86XK_CONTRAST_ADJUST",
+ "DOM_VK_XF86XK_COPY",
+ "DOM_VK_XF86XK_CUT",
+ "DOM_VK_XF86XK_CYCLE_ANGLE",
+ "DOM_VK_XF86XK_DISPLAY",
+ "DOM_VK_XF86XK_DOCUMENTS",
+ "DOM_VK_XF86XK_DOS",
+ "DOM_VK_XF86XK_EJECT",
+ "DOM_VK_XF86XK_EXCEL",
+ "DOM_VK_XF86XK_EXPLORER",
+ "DOM_VK_XF86XK_FAVORITES",
+ "DOM_VK_XF86XK_FINANCE",
+ "DOM_VK_XF86XK_FORWARD",
+ "DOM_VK_XF86XK_FRAME_BACK",
+ "DOM_VK_XF86XK_FRAME_FORWARD",
+ "DOM_VK_XF86XK_GAME",
+ "DOM_VK_XF86XK_GO",
+ "DOM_VK_XF86XK_GREEN",
+ "DOM_VK_XF86XK_HIBERNATE",
+ "DOM_VK_XF86XK_HISTORY",
+ "DOM_VK_XF86XK_HOME_PAGE",
+ "DOM_VK_XF86XK_HOT_LINKS",
+ "DOM_VK_XF86XK_I_TOUCH",
+ "DOM_VK_XF86XK_KBD_BRIGHTNESS_DOWN",
+ "DOM_VK_XF86XK_KBD_BRIGHTNESS_UP",
+ "DOM_VK_XF86XK_KBD_LIGHT_ON_OFF",
+ "DOM_VK_XF86XK_LAUNCH0",
+ "DOM_VK_XF86XK_LAUNCH1",
+ "DOM_VK_XF86XK_LAUNCH2",
+ "DOM_VK_XF86XK_LAUNCH3",
+ "DOM_VK_XF86XK_LAUNCH4",
+ "DOM_VK_XF86XK_LAUNCH5",
+ "DOM_VK_XF86XK_LAUNCH6",
+ "DOM_VK_XF86XK_LAUNCH7",
+ "DOM_VK_XF86XK_LAUNCH8",
+ "DOM_VK_XF86XK_LAUNCH9",
+ "DOM_VK_XF86XK_LAUNCH_A",
+ "DOM_VK_XF86XK_LAUNCH_B",
+ "DOM_VK_XF86XK_LAUNCH_C",
+ "DOM_VK_XF86XK_LAUNCH_D",
+ "DOM_VK_XF86XK_LAUNCH_E",
+ "DOM_VK_XF86XK_LAUNCH_F",
+ "DOM_VK_XF86XK_LIGHT_BULB",
+ "DOM_VK_XF86XK_LOG_OFF",
+ "DOM_VK_XF86XK_MAIL",
+ "DOM_VK_XF86XK_MAIL_FORWARD",
+ "DOM_VK_XF86XK_MARKET",
+ "DOM_VK_XF86XK_MEETING",
+ "DOM_VK_XF86XK_MEMO",
+ "DOM_VK_XF86XK_MENU_KB",
+ "DOM_VK_XF86XK_MENU_PB",
+ "DOM_VK_XF86XK_MESSENGER",
+ "DOM_VK_XF86XK_MON_BRIGHTNESS_DOWN",
+ "DOM_VK_XF86XK_MON_BRIGHTNESS_UP",
+ "DOM_VK_XF86XK_MUSIC",
+ "DOM_VK_XF86XK_MY_COMPUTER",
+ "DOM_VK_XF86XK_MY_SITES",
+ "DOM_VK_XF86XK_NEW",
+ "DOM_VK_XF86XK_NEWS",
+ "DOM_VK_XF86XK_OFFICE_HOME",
+ "DOM_VK_XF86XK_OPEN",
+ "DOM_VK_XF86XK_OPEN_URL",
+ "DOM_VK_XF86XK_OPTION",
+ "DOM_VK_XF86XK_PASTE",
+ "DOM_VK_XF86XK_PHONE",
+ "DOM_VK_XF86XK_PICTURES",
+ "DOM_VK_XF86XK_POWER_DOWN",
+ "DOM_VK_XF86XK_POWER_OFF",
+ "DOM_VK_XF86XK_RED",
+ "DOM_VK_XF86XK_REFRESH",
+ "DOM_VK_XF86XK_RELOAD",
+ "DOM_VK_XF86XK_REPLY",
+ "DOM_VK_XF86XK_ROCKER_DOWN",
+ "DOM_VK_XF86XK_ROCKER_ENTER",
+ "DOM_VK_XF86XK_ROCKER_UP",
+ "DOM_VK_XF86XK_ROTATE_WINDOWS",
+ "DOM_VK_XF86XK_ROTATION_KB",
+ "DOM_VK_XF86XK_ROTATION_PB",
+ "DOM_VK_XF86XK_SAVE",
+ "DOM_VK_XF86XK_SCREEN_SAVER",
+ "DOM_VK_XF86XK_SCROLL_CLICK",
+ "DOM_VK_XF86XK_SCROLL_DOWN",
+ "DOM_VK_XF86XK_SCROLL_UP",
+ "DOM_VK_XF86XK_SEARCH",
+ "DOM_VK_XF86XK_SEND",
+ "DOM_VK_XF86XK_SHOP",
+ "DOM_VK_XF86XK_SPELL",
+ "DOM_VK_XF86XK_SPLIT_SCREEN",
+ "DOM_VK_XF86XK_STANDBY",
+ "DOM_VK_XF86XK_START",
+ "DOM_VK_XF86XK_STOP",
+ "DOM_VK_XF86XK_SUBTITLE",
+ "DOM_VK_XF86XK_SUPPORT",
+ "DOM_VK_XF86XK_SUSPEND",
+ "DOM_VK_XF86XK_TASK_PANE",
+ "DOM_VK_XF86XK_TERMINAL",
+ "DOM_VK_XF86XK_TIME",
+ "DOM_VK_XF86XK_TOOLS",
+ "DOM_VK_XF86XK_TOP_MENU",
+ "DOM_VK_XF86XK_TO_DO_LIST",
+ "DOM_VK_XF86XK_TRAVEL",
+ "DOM_VK_XF86XK_USER1KB",
+ "DOM_VK_XF86XK_USER2KB",
+ "DOM_VK_XF86XK_USER_PB",
+ "DOM_VK_XF86XK_UWB",
+ "DOM_VK_XF86XK_VENDOR_HOME",
+ "DOM_VK_XF86XK_VIDEO",
+ "DOM_VK_XF86XK_VIEW",
+ "DOM_VK_XF86XK_WAKE_UP",
+ "DOM_VK_XF86XK_WEB_CAM",
+ "DOM_VK_XF86XK_WHEEL_BUTTON",
+ "DOM_VK_XF86XK_WLAN",
+ "DOM_VK_XF86XK_WORD",
+ "DOM_VK_XF86XK_WWW",
+ "DOM_VK_XF86XK_XFER",
+ "DOM_VK_XF86XK_YELLOW",
+ "DOM_VK_XF86XK_ZOOM_IN",
+ "DOM_VK_XF86XK_ZOOM_OUT",
+ "DOM_VK_Y",
+ "DOM_VK_Z",
+ "DOM_VK_ZOOM",
+ "DONE",
+ "DONT_CARE",
+ "DOWNLOADING",
+ "DRAGDROP",
+ "DRAW_BUFFER0",
+ "DRAW_BUFFER1",
+ "DRAW_BUFFER10",
+ "DRAW_BUFFER11",
+ "DRAW_BUFFER12",
+ "DRAW_BUFFER13",
+ "DRAW_BUFFER14",
+ "DRAW_BUFFER15",
+ "DRAW_BUFFER2",
+ "DRAW_BUFFER3",
+ "DRAW_BUFFER4",
+ "DRAW_BUFFER5",
+ "DRAW_BUFFER6",
+ "DRAW_BUFFER7",
+ "DRAW_BUFFER8",
+ "DRAW_BUFFER9",
+ "DRAW_FRAMEBUFFER",
+ "DRAW_FRAMEBUFFER_BINDING",
+ "DST_ALPHA",
+ "DST_COLOR",
+ "DYNAMIC_COPY",
+ "DYNAMIC_DRAW",
+ "DYNAMIC_READ",
+ "DataChannel",
+ "DataTransfer",
+ "DataTransferItem",
+ "DataTransferItemList",
+ "DataView",
+ "Date",
+ "DateTimeFormat",
+ "DecompressionStream",
+ "DelayNode",
+ "DeprecationReportBody",
+ "DesktopNotification",
+ "DesktopNotificationCenter",
+ "DeviceLightEvent",
+ "DeviceMotionEvent",
+ "DeviceMotionEventAcceleration",
+ "DeviceMotionEventRotationRate",
+ "DeviceOrientationEvent",
+ "DeviceProximityEvent",
+ "DeviceStorage",
+ "DeviceStorageChangeEvent",
+ "Directory",
+ "DisplayNames",
+ "Document",
+ "DocumentFragment",
+ "DocumentTimeline",
+ "DocumentType",
+ "DragEvent",
+ "DynamicsCompressorNode",
+ "E",
+ "ELEMENT_ARRAY_BUFFER",
+ "ELEMENT_ARRAY_BUFFER_BINDING",
+ "ELEMENT_NODE",
+ "EMPTY",
+ "ENCODING_ERR",
+ "ENDED",
+ "END_TO_END",
+ "END_TO_START",
+ "ENTITY_NODE",
+ "ENTITY_REFERENCE_NODE",
+ "EPSILON",
+ "EQUAL",
+ "EQUALPOWER",
+ "ERROR",
+ "EXPONENTIAL_DISTANCE",
+ "exports",
+ "Element",
+ "ElementInternals",
+ "ElementQuery",
+ "EnterPictureInPictureEvent",
+ "Entity",
+ "EntityReference",
+ "Error",
+ "ErrorEvent",
+ "EvalError",
+ "Event",
+ "EventException",
+ "EventSource",
+ "EventTarget",
+ "External",
+ "FASTEST",
+ "FIDOSDK",
+ "FILTER_ACCEPT",
+ "FILTER_INTERRUPT",
+ "FILTER_REJECT",
+ "FILTER_SKIP",
+ "FINISHED_STATE",
+ "FIRST_ORDERED_NODE_TYPE",
+ "FLOAT",
+ "FLOAT_32_UNSIGNED_INT_24_8_REV",
+ "FLOAT_MAT2",
+ "FLOAT_MAT2x3",
+ "FLOAT_MAT2x4",
+ "FLOAT_MAT3",
+ "FLOAT_MAT3x2",
+ "FLOAT_MAT3x4",
+ "FLOAT_MAT4",
+ "FLOAT_MAT4x2",
+ "FLOAT_MAT4x3",
+ "FLOAT_VEC2",
+ "FLOAT_VEC3",
+ "FLOAT_VEC4",
+ "FOCUS",
+ "FONT_FACE_RULE",
+ "FONT_FEATURE_VALUES_RULE",
+ "FRAGMENT_SHADER",
+ "FRAGMENT_SHADER_DERIVATIVE_HINT",
+ "FRAGMENT_SHADER_DERIVATIVE_HINT_OES",
+ "FRAMEBUFFER",
+ "FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE",
+ "FRAMEBUFFER_ATTACHMENT_BLUE_SIZE",
+ "FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING",
+ "FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE",
+ "FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE",
+ "FRAMEBUFFER_ATTACHMENT_GREEN_SIZE",
+ "FRAMEBUFFER_ATTACHMENT_OBJECT_NAME",
+ "FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE",
+ "FRAMEBUFFER_ATTACHMENT_RED_SIZE",
+ "FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE",
+ "FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE",
+ "FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER",
+ "FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL",
+ "FRAMEBUFFER_BINDING",
+ "FRAMEBUFFER_COMPLETE",
+ "FRAMEBUFFER_DEFAULT",
+ "FRAMEBUFFER_INCOMPLETE_ATTACHMENT",
+ "FRAMEBUFFER_INCOMPLETE_DIMENSIONS",
+ "FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT",
+ "FRAMEBUFFER_INCOMPLETE_MULTISAMPLE",
+ "FRAMEBUFFER_UNSUPPORTED",
+ "FRONT",
+ "FRONT_AND_BACK",
+ "FRONT_FACE",
+ "FUNC_ADD",
+ "FUNC_REVERSE_SUBTRACT",
+ "FUNC_SUBTRACT",
+ "FeaturePolicy",
+ "FeaturePolicyViolationReportBody",
+ "FederatedCredential",
+ "Feed",
+ "FeedEntry",
+ "File",
+ "FileError",
+ "FileList",
+ "FileReader",
+ "FileSystem",
+ "FileSystemDirectoryEntry",
+ "FileSystemDirectoryReader",
+ "FileSystemEntry",
+ "FileSystemFileEntry",
+ "FinalizationRegistry",
+ "FindInPage",
+ "Float32Array",
+ "Float64Array",
+ "FocusEvent",
+ "FontFace",
+ "FontFaceSet",
+ "FontFaceSetLoadEvent",
+ "FormData",
+ "FormDataEvent",
+ "FragmentDirective",
+ "Function",
+ "GENERATE_MIPMAP_HINT",
+ "GEQUAL",
+ "GREATER",
+ "GREEN_BITS",
+ "GainNode",
+ "Gamepad",
+ "GamepadAxisMoveEvent",
+ "GamepadButton",
+ "GamepadButtonEvent",
+ "GamepadEvent",
+ "GamepadHapticActuator",
+ "GamepadPose",
+ "Geolocation",
+ "GeolocationCoordinates",
+ "GeolocationPosition",
+ "GeolocationPositionError",
+ "GestureEvent",
+ "Global",
+ "Gyroscope",
+ "HALF_FLOAT",
+ "HAVE_CURRENT_DATA",
+ "HAVE_ENOUGH_DATA",
+ "HAVE_FUTURE_DATA",
+ "HAVE_METADATA",
+ "HAVE_NOTHING",
+ "HEADERS_RECEIVED",
+ "HIDDEN",
+ "HIERARCHY_REQUEST_ERR",
+ "HIGHPASS",
+ "HIGHSHELF",
+ "HIGH_FLOAT",
+ "HIGH_INT",
+ "HORIZONTAL",
+ "HORIZONTAL_AXIS",
+ "HRTF",
+ "HTMLAllCollection",
+ "HTMLAnchorElement",
+ "HTMLAppletElement",
+ "HTMLAreaElement",
+ "HTMLAudioElement",
+ "HTMLBRElement",
+ "HTMLBaseElement",
+ "HTMLBaseFontElement",
+ "HTMLBlockquoteElement",
+ "HTMLBodyElement",
+ "HTMLButtonElement",
+ "HTMLCanvasElement",
+ "HTMLCollection",
+ "HTMLCommandElement",
+ "HTMLContentElement",
+ "HTMLDListElement",
+ "HTMLDataElement",
+ "HTMLDataListElement",
+ "HTMLDetailsElement",
+ "HTMLDialogElement",
+ "HTMLDirectoryElement",
+ "HTMLDivElement",
+ "HTMLDocument",
+ "HTMLElement",
+ "HTMLEmbedElement",
+ "HTMLFieldSetElement",
+ "HTMLFontElement",
+ "HTMLFormControlsCollection",
+ "HTMLFormElement",
+ "HTMLFrameElement",
+ "HTMLFrameSetElement",
+ "HTMLHRElement",
+ "HTMLHeadElement",
+ "HTMLHeadingElement",
+ "HTMLHtmlElement",
+ "HTMLIFrameElement",
+ "HTMLImageElement",
+ "HTMLInputElement",
+ "HTMLIsIndexElement",
+ "HTMLKeygenElement",
+ "HTMLLIElement",
+ "HTMLLabelElement",
+ "HTMLLegendElement",
+ "HTMLLinkElement",
+ "HTMLMapElement",
+ "HTMLMarqueeElement",
+ "HTMLMediaElement",
+ "HTMLMenuElement",
+ "HTMLMenuItemElement",
+ "HTMLMetaElement",
+ "HTMLMeterElement",
+ "HTMLModElement",
+ "HTMLOListElement",
+ "HTMLObjectElement",
+ "HTMLOptGroupElement",
+ "HTMLOptionElement",
+ "HTMLOptionsCollection",
+ "HTMLOutputElement",
+ "HTMLParagraphElement",
+ "HTMLParamElement",
+ "HTMLPictureElement",
+ "HTMLPreElement",
+ "HTMLProgressElement",
+ "HTMLPropertiesCollection",
+ "HTMLQuoteElement",
+ "HTMLScriptElement",
+ "HTMLSelectElement",
+ "HTMLShadowElement",
+ "HTMLSlotElement",
+ "HTMLSourceElement",
+ "HTMLSpanElement",
+ "HTMLStyleElement",
+ "HTMLTableCaptionElement",
+ "HTMLTableCellElement",
+ "HTMLTableColElement",
+ "HTMLTableElement",
+ "HTMLTableRowElement",
+ "HTMLTableSectionElement",
+ "HTMLTemplateElement",
+ "HTMLTextAreaElement",
+ "HTMLTimeElement",
+ "HTMLTitleElement",
+ "HTMLTrackElement",
+ "HTMLUListElement",
+ "HTMLUnknownElement",
+ "HTMLVideoElement",
+ "HashChangeEvent",
+ "Headers",
+ "History",
+ "Hz",
+ "ICE_CHECKING",
+ "ICE_CLOSED",
+ "ICE_COMPLETED",
+ "ICE_CONNECTED",
+ "ICE_FAILED",
+ "ICE_GATHERING",
+ "ICE_WAITING",
+ "IDBCursor",
+ "IDBCursorWithValue",
+ "IDBDatabase",
+ "IDBDatabaseException",
+ "IDBFactory",
+ "IDBFileHandle",
+ "IDBFileRequest",
+ "IDBIndex",
+ "IDBKeyRange",
+ "IDBMutableFile",
+ "IDBObjectStore",
+ "IDBOpenDBRequest",
+ "IDBRequest",
+ "IDBTransaction",
+ "IDBVersionChangeEvent",
+ "IDLE",
+ "IIRFilterNode",
+ "IMPLEMENTATION_COLOR_READ_FORMAT",
+ "IMPLEMENTATION_COLOR_READ_TYPE",
+ "IMPORT_RULE",
+ "INCR",
+ "INCR_WRAP",
+ "INDEX_SIZE_ERR",
+ "INT",
+ "INTERLEAVED_ATTRIBS",
+ "INT_2_10_10_10_REV",
+ "INT_SAMPLER_2D",
+ "INT_SAMPLER_2D_ARRAY",
+ "INT_SAMPLER_3D",
+ "INT_SAMPLER_CUBE",
+ "INT_VEC2",
+ "INT_VEC3",
+ "INT_VEC4",
+ "INUSE_ATTRIBUTE_ERR",
+ "INVALID_ACCESS_ERR",
+ "INVALID_CHARACTER_ERR",
+ "INVALID_ENUM",
+ "INVALID_EXPRESSION_ERR",
+ "INVALID_FRAMEBUFFER_OPERATION",
+ "INVALID_INDEX",
+ "INVALID_MODIFICATION_ERR",
+ "INVALID_NODE_TYPE_ERR",
+ "INVALID_OPERATION",
+ "INVALID_STATE_ERR",
+ "INVALID_VALUE",
+ "INVERSE_DISTANCE",
+ "INVERT",
+ "IceCandidate",
+ "IdleDeadline",
+ "Image",
+ "ImageBitmap",
+ "ImageBitmapRenderingContext",
+ "ImageCapture",
+ "ImageData",
+ "Infinity",
+ "InputDeviceCapabilities",
+ "InputDeviceInfo",
+ "InputEvent",
+ "InputMethodContext",
+ "InstallTrigger",
+ "InstallTriggerImpl",
+ "Instance",
+ "Int16Array",
+ "Int32Array",
+ "Int8Array",
+ "Intent",
+ "InternalError",
+ "IntersectionObserver",
+ "IntersectionObserverEntry",
+ "Intl",
+ "IsSearchProviderInstalled",
+ "Iterator",
+ "JSON",
+ "KEEP",
+ "KEYDOWN",
+ "KEYFRAMES_RULE",
+ "KEYFRAME_RULE",
+ "KEYPRESS",
+ "KEYUP",
+ "KeyEvent",
+ "Keyboard",
+ "KeyboardEvent",
+ "KeyboardLayoutMap",
+ "KeyframeEffect",
+ "LENGTHADJUST_SPACING",
+ "LENGTHADJUST_SPACINGANDGLYPHS",
+ "LENGTHADJUST_UNKNOWN",
+ "LEQUAL",
+ "LESS",
+ "LINEAR",
+ "LINEAR_DISTANCE",
+ "LINEAR_MIPMAP_LINEAR",
+ "LINEAR_MIPMAP_NEAREST",
+ "LINES",
+ "LINE_LOOP",
+ "LINE_STRIP",
+ "LINE_WIDTH",
+ "LINK_STATUS",
+ "LIVE",
+ "LN10",
+ "LN2",
+ "LOADED",
+ "LOADING",
+ "LOG10E",
+ "LOG2E",
+ "LOWPASS",
+ "LOWSHELF",
+ "LOW_FLOAT",
+ "LOW_INT",
+ "LSException",
+ "LSParserFilter",
+ "LUMINANCE",
+ "LUMINANCE_ALPHA",
+ "LargestContentfulPaint",
+ "LayoutShift",
+ "LayoutShiftAttribution",
+ "LinearAccelerationSensor",
+ "LinkError",
+ "ListFormat",
+ "LocalMediaStream",
+ "Locale",
+ "Location",
+ "Lock",
+ "LockManager",
+ "MAX",
+ "MAX_3D_TEXTURE_SIZE",
+ "MAX_ARRAY_TEXTURE_LAYERS",
+ "MAX_CLIENT_WAIT_TIMEOUT_WEBGL",
+ "MAX_COLOR_ATTACHMENTS",
+ "MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS",
+ "MAX_COMBINED_TEXTURE_IMAGE_UNITS",
+ "MAX_COMBINED_UNIFORM_BLOCKS",
+ "MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS",
+ "MAX_CUBE_MAP_TEXTURE_SIZE",
+ "MAX_DRAW_BUFFERS",
+ "MAX_ELEMENTS_INDICES",
+ "MAX_ELEMENTS_VERTICES",
+ "MAX_ELEMENT_INDEX",
+ "MAX_FRAGMENT_INPUT_COMPONENTS",
+ "MAX_FRAGMENT_UNIFORM_BLOCKS",
+ "MAX_FRAGMENT_UNIFORM_COMPONENTS",
+ "MAX_FRAGMENT_UNIFORM_VECTORS",
+ "MAX_PROGRAM_TEXEL_OFFSET",
+ "MAX_RENDERBUFFER_SIZE",
+ "MAX_SAFE_INTEGER",
+ "MAX_SAMPLES",
+ "MAX_SERVER_WAIT_TIMEOUT",
+ "MAX_TEXTURE_IMAGE_UNITS",
+ "MAX_TEXTURE_LOD_BIAS",
+ "MAX_TEXTURE_MAX_ANISOTROPY_EXT",
+ "MAX_TEXTURE_SIZE",
+ "MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS",
+ "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS",
+ "MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS",
+ "MAX_UNIFORM_BLOCK_SIZE",
+ "MAX_UNIFORM_BUFFER_BINDINGS",
+ "MAX_VALUE",
+ "MAX_VARYING_COMPONENTS",
+ "MAX_VARYING_VECTORS",
+ "MAX_VERTEX_ATTRIBS",
+ "MAX_VERTEX_OUTPUT_COMPONENTS",
+ "MAX_VERTEX_TEXTURE_IMAGE_UNITS",
+ "MAX_VERTEX_UNIFORM_BLOCKS",
+ "MAX_VERTEX_UNIFORM_COMPONENTS",
+ "MAX_VERTEX_UNIFORM_VECTORS",
+ "MAX_VIEWPORT_DIMS",
+ "MEDIA_ERR_ABORTED",
+ "MEDIA_ERR_DECODE",
+ "MEDIA_ERR_ENCRYPTED",
+ "MEDIA_ERR_NETWORK",
+ "MEDIA_ERR_SRC_NOT_SUPPORTED",
+ "MEDIA_KEYERR_CLIENT",
+ "MEDIA_KEYERR_DOMAIN",
+ "MEDIA_KEYERR_HARDWARECHANGE",
+ "MEDIA_KEYERR_OUTPUT",
+ "MEDIA_KEYERR_SERVICE",
+ "MEDIA_KEYERR_UNKNOWN",
+ "MEDIA_RULE",
+ "MEDIUM_FLOAT",
+ "MEDIUM_INT",
+ "META_MASK",
+ "MIDIAccess",
+ "MIDIConnectionEvent",
+ "MIDIInput",
+ "MIDIInputMap",
+ "MIDIMessageEvent",
+ "MIDIOutput",
+ "MIDIOutputMap",
+ "MIDIPort",
+ "MIN",
+ "MIN_PROGRAM_TEXEL_OFFSET",
+ "MIN_SAFE_INTEGER",
+ "MIN_VALUE",
+ "MIRRORED_REPEAT",
+ "MODE_ASYNCHRONOUS",
+ "MODE_SYNCHRONOUS",
+ "MODIFICATION",
+ "MOUSEDOWN",
+ "MOUSEDRAG",
+ "MOUSEMOVE",
+ "MOUSEOUT",
+ "MOUSEOVER",
+ "MOUSEUP",
+ "MOZ_KEYFRAMES_RULE",
+ "MOZ_KEYFRAME_RULE",
+ "MOZ_SOURCE_CURSOR",
+ "MOZ_SOURCE_ERASER",
+ "MOZ_SOURCE_KEYBOARD",
+ "MOZ_SOURCE_MOUSE",
+ "MOZ_SOURCE_PEN",
+ "MOZ_SOURCE_TOUCH",
+ "MOZ_SOURCE_UNKNOWN",
+ "MSGESTURE_FLAG_BEGIN",
+ "MSGESTURE_FLAG_CANCEL",
+ "MSGESTURE_FLAG_END",
+ "MSGESTURE_FLAG_INERTIA",
+ "MSGESTURE_FLAG_NONE",
+ "MSPOINTER_TYPE_MOUSE",
+ "MSPOINTER_TYPE_PEN",
+ "MSPOINTER_TYPE_TOUCH",
+ "MS_ASYNC_CALLBACK_STATUS_ASSIGN_DELEGATE",
+ "MS_ASYNC_CALLBACK_STATUS_CANCEL",
+ "MS_ASYNC_CALLBACK_STATUS_CHOOSEANY",
+ "MS_ASYNC_CALLBACK_STATUS_ERROR",
+ "MS_ASYNC_CALLBACK_STATUS_JOIN",
+ "MS_ASYNC_OP_STATUS_CANCELED",
+ "MS_ASYNC_OP_STATUS_ERROR",
+ "MS_ASYNC_OP_STATUS_SUCCESS",
+ "MS_MANIPULATION_STATE_ACTIVE",
+ "MS_MANIPULATION_STATE_CANCELLED",
+ "MS_MANIPULATION_STATE_COMMITTED",
+ "MS_MANIPULATION_STATE_DRAGGING",
+ "MS_MANIPULATION_STATE_INERTIA",
+ "MS_MANIPULATION_STATE_PRESELECT",
+ "MS_MANIPULATION_STATE_SELECTING",
+ "MS_MANIPULATION_STATE_STOPPED",
+ "MS_MEDIA_ERR_ENCRYPTED",
+ "MS_MEDIA_KEYERR_CLIENT",
+ "MS_MEDIA_KEYERR_DOMAIN",
+ "MS_MEDIA_KEYERR_HARDWARECHANGE",
+ "MS_MEDIA_KEYERR_OUTPUT",
+ "MS_MEDIA_KEYERR_SERVICE",
+ "MS_MEDIA_KEYERR_UNKNOWN",
+ "Map",
+ "Math",
+ "MathMLElement",
+ "MediaCapabilities",
+ "MediaCapabilitiesInfo",
+ "MediaController",
+ "MediaDeviceInfo",
+ "MediaDevices",
+ "MediaElementAudioSourceNode",
+ "MediaEncryptedEvent",
+ "MediaError",
+ "MediaKeyError",
+ "MediaKeyEvent",
+ "MediaKeyMessageEvent",
+ "MediaKeyNeededEvent",
+ "MediaKeySession",
+ "MediaKeyStatusMap",
+ "MediaKeySystemAccess",
+ "MediaKeys",
+ "MediaList",
+ "MediaMetadata",
+ "MediaQueryList",
+ "MediaQueryListEvent",
+ "MediaRecorder",
+ "MediaRecorderErrorEvent",
+ "MediaSession",
+ "MediaSettingsRange",
+ "MediaSource",
+ "MediaStream",
+ "MediaStreamAudioDestinationNode",
+ "MediaStreamAudioSourceNode",
+ "MediaStreamEvent",
+ "MediaStreamTrack",
+ "MediaStreamTrackAudioSourceNode",
+ "MediaStreamTrackEvent",
+ "Memory",
+ "MessageChannel",
+ "MessageEvent",
+ "MessagePort",
+ "Methods",
+ "MimeType",
+ "MimeTypeArray",
+ "Module",
+ "MouseEvent",
+ "MouseScrollEvent",
+ "MozAnimation",
+ "MozAnimationDelay",
+ "MozAnimationDirection",
+ "MozAnimationDuration",
+ "MozAnimationFillMode",
+ "MozAnimationIterationCount",
+ "MozAnimationName",
+ "MozAnimationPlayState",
+ "MozAnimationTimingFunction",
+ "MozAppearance",
+ "MozBackfaceVisibility",
+ "MozBinding",
+ "MozBorderBottomColors",
+ "MozBorderEnd",
+ "MozBorderEndColor",
+ "MozBorderEndStyle",
+ "MozBorderEndWidth",
+ "MozBorderImage",
+ "MozBorderLeftColors",
+ "MozBorderRightColors",
+ "MozBorderStart",
+ "MozBorderStartColor",
+ "MozBorderStartStyle",
+ "MozBorderStartWidth",
+ "MozBorderTopColors",
+ "MozBoxAlign",
+ "MozBoxDirection",
+ "MozBoxFlex",
+ "MozBoxOrdinalGroup",
+ "MozBoxOrient",
+ "MozBoxPack",
+ "MozBoxSizing",
+ "MozCSSKeyframeRule",
+ "MozCSSKeyframesRule",
+ "MozColumnCount",
+ "MozColumnFill",
+ "MozColumnGap",
+ "MozColumnRule",
+ "MozColumnRuleColor",
+ "MozColumnRuleStyle",
+ "MozColumnRuleWidth",
+ "MozColumnWidth",
+ "MozColumns",
+ "MozContactChangeEvent",
+ "MozFloatEdge",
+ "MozFontFeatureSettings",
+ "MozFontLanguageOverride",
+ "MozForceBrokenImageIcon",
+ "MozHyphens",
+ "MozImageRegion",
+ "MozMarginEnd",
+ "MozMarginStart",
+ "MozMmsEvent",
+ "MozMmsMessage",
+ "MozMobileMessageThread",
+ "MozOSXFontSmoothing",
+ "MozOrient",
+ "MozOsxFontSmoothing",
+ "MozOutlineRadius",
+ "MozOutlineRadiusBottomleft",
+ "MozOutlineRadiusBottomright",
+ "MozOutlineRadiusTopleft",
+ "MozOutlineRadiusTopright",
+ "MozPaddingEnd",
+ "MozPaddingStart",
+ "MozPerspective",
+ "MozPerspectiveOrigin",
+ "MozPowerManager",
+ "MozSettingsEvent",
+ "MozSmsEvent",
+ "MozSmsMessage",
+ "MozStackSizing",
+ "MozTabSize",
+ "MozTextAlignLast",
+ "MozTextDecorationColor",
+ "MozTextDecorationLine",
+ "MozTextDecorationStyle",
+ "MozTextSizeAdjust",
+ "MozTransform",
+ "MozTransformOrigin",
+ "MozTransformStyle",
+ "MozTransition",
+ "MozTransitionDelay",
+ "MozTransitionDuration",
+ "MozTransitionProperty",
+ "MozTransitionTimingFunction",
+ "MozUserFocus",
+ "MozUserInput",
+ "MozUserModify",
+ "MozUserSelect",
+ "MozWindowDragging",
+ "MozWindowShadow",
+ "MutationEvent",
+ "MutationObserver",
+ "MutationRecord",
+ "NAMESPACE_ERR",
+ "NAMESPACE_RULE",
+ "NEAREST",
+ "NEAREST_MIPMAP_LINEAR",
+ "NEAREST_MIPMAP_NEAREST",
+ "NEGATIVE_INFINITY",
+ "NETWORK_EMPTY",
+ "NETWORK_ERR",
+ "NETWORK_IDLE",
+ "NETWORK_LOADED",
+ "NETWORK_LOADING",
+ "NETWORK_NO_SOURCE",
+ "NEVER",
+ "NEW",
+ "NEXT",
+ "NEXT_NO_DUPLICATE",
+ "NICEST",
+ "NODE_AFTER",
+ "NODE_BEFORE",
+ "NODE_BEFORE_AND_AFTER",
+ "NODE_INSIDE",
+ "NONE",
+ "NON_TRANSIENT_ERR",
+ "NOTATION_NODE",
+ "NOTCH",
+ "NOTEQUAL",
+ "NOT_ALLOWED_ERR",
+ "NOT_FOUND_ERR",
+ "NOT_READABLE_ERR",
+ "NOT_SUPPORTED_ERR",
+ "NO_DATA_ALLOWED_ERR",
+ "NO_ERR",
+ "NO_ERROR",
+ "NO_MODIFICATION_ALLOWED_ERR",
+ "NUMBER_TYPE",
+ "NUM_COMPRESSED_TEXTURE_FORMATS",
+ "NaN",
+ "NamedNodeMap",
+ "NavigationPreloadManager",
+ "Navigator",
+ "NearbyLinks",
+ "NetworkInformation",
+ "Node",
+ "NodeFilter",
+ "NodeIterator",
+ "NodeList",
+ "Notation",
+ "Notification",
+ "NotifyPaintEvent",
+ "Number",
+ "NumberFormat",
+ "OBJECT_TYPE",
+ "OBSOLETE",
+ "OK",
+ "ONE",
+ "ONE_MINUS_CONSTANT_ALPHA",
+ "ONE_MINUS_CONSTANT_COLOR",
+ "ONE_MINUS_DST_ALPHA",
+ "ONE_MINUS_DST_COLOR",
+ "ONE_MINUS_SRC_ALPHA",
+ "ONE_MINUS_SRC_COLOR",
+ "OPEN",
+ "OPENED",
+ "OPENING",
+ "ORDERED_NODE_ITERATOR_TYPE",
+ "ORDERED_NODE_SNAPSHOT_TYPE",
+ "OTHER_ERROR",
+ "OUT_OF_MEMORY",
+ "Object",
+ "OfflineAudioCompletionEvent",
+ "OfflineAudioContext",
+ "OfflineResourceList",
+ "OffscreenCanvas",
+ "OffscreenCanvasRenderingContext2D",
+ "Option",
+ "OrientationSensor",
+ "OscillatorNode",
+ "OverconstrainedError",
+ "OverflowEvent",
+ "PACK_ALIGNMENT",
+ "PACK_ROW_LENGTH",
+ "PACK_SKIP_PIXELS",
+ "PACK_SKIP_ROWS",
+ "PAGE_RULE",
+ "PARSE_ERR",
+ "PATHSEG_ARC_ABS",
+ "PATHSEG_ARC_REL",
+ "PATHSEG_CLOSEPATH",
+ "PATHSEG_CURVETO_CUBIC_ABS",
+ "PATHSEG_CURVETO_CUBIC_REL",
+ "PATHSEG_CURVETO_CUBIC_SMOOTH_ABS",
+ "PATHSEG_CURVETO_CUBIC_SMOOTH_REL",
+ "PATHSEG_CURVETO_QUADRATIC_ABS",
+ "PATHSEG_CURVETO_QUADRATIC_REL",
+ "PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS",
+ "PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL",
+ "PATHSEG_LINETO_ABS",
+ "PATHSEG_LINETO_HORIZONTAL_ABS",
+ "PATHSEG_LINETO_HORIZONTAL_REL",
+ "PATHSEG_LINETO_REL",
+ "PATHSEG_LINETO_VERTICAL_ABS",
+ "PATHSEG_LINETO_VERTICAL_REL",
+ "PATHSEG_MOVETO_ABS",
+ "PATHSEG_MOVETO_REL",
+ "PATHSEG_UNKNOWN",
+ "PATH_EXISTS_ERR",
+ "PEAKING",
+ "PERMISSION_DENIED",
+ "PERSISTENT",
+ "PI",
+ "PIXEL_PACK_BUFFER",
+ "PIXEL_PACK_BUFFER_BINDING",
+ "PIXEL_UNPACK_BUFFER",
+ "PIXEL_UNPACK_BUFFER_BINDING",
+ "PLAYING_STATE",
+ "POINTS",
+ "POLYGON_OFFSET_FACTOR",
+ "POLYGON_OFFSET_FILL",
+ "POLYGON_OFFSET_UNITS",
+ "POSITION_UNAVAILABLE",
+ "POSITIVE_INFINITY",
+ "PREV",
+ "PREV_NO_DUPLICATE",
+ "PROCESSING_INSTRUCTION_NODE",
+ "PageChangeEvent",
+ "PageTransitionEvent",
+ "PaintRequest",
+ "PaintRequestList",
+ "PannerNode",
+ "PasswordCredential",
+ "Path2D",
+ "PaymentAddress",
+ "PaymentInstruments",
+ "PaymentManager",
+ "PaymentMethodChangeEvent",
+ "PaymentRequest",
+ "PaymentRequestUpdateEvent",
+ "PaymentResponse",
+ "Performance",
+ "PerformanceElementTiming",
+ "PerformanceEntry",
+ "PerformanceEventTiming",
+ "PerformanceLongTaskTiming",
+ "PerformanceMark",
+ "PerformanceMeasure",
+ "PerformanceNavigation",
+ "PerformanceNavigationTiming",
+ "PerformanceObserver",
+ "PerformanceObserverEntryList",
+ "PerformancePaintTiming",
+ "PerformanceResourceTiming",
+ "PerformanceServerTiming",
+ "PerformanceTiming",
+ "PeriodicSyncManager",
+ "PeriodicWave",
+ "PermissionStatus",
+ "Permissions",
+ "PhotoCapabilities",
+ "PictureInPictureWindow",
+ "Plugin",
+ "PluginArray",
+ "PluralRules",
+ "PointerEvent",
+ "PopStateEvent",
+ "PopupBlockedEvent",
+ "Presentation",
+ "PresentationAvailability",
+ "PresentationConnection",
+ "PresentationConnectionAvailableEvent",
+ "PresentationConnectionCloseEvent",
+ "PresentationConnectionList",
+ "PresentationReceiver",
+ "PresentationRequest",
+ "ProcessingInstruction",
+ "ProgressEvent",
+ "Promise",
+ "PromiseRejectionEvent",
+ "PropertyNodeList",
+ "Proxy",
+ "PublicKeyCredential",
+ "PushManager",
+ "PushSubscription",
+ "PushSubscriptionOptions",
+ "Q",
+ "QUERY_RESULT",
+ "QUERY_RESULT_AVAILABLE",
+ "QUOTA_ERR",
+ "QUOTA_EXCEEDED_ERR",
+ "QueryInterface",
+ "R11F_G11F_B10F",
+ "R16F",
+ "R16I",
+ "R16UI",
+ "R32F",
+ "R32I",
+ "R32UI",
+ "R8",
+ "R8I",
+ "R8UI",
+ "R8_SNORM",
+ "RASTERIZER_DISCARD",
+ "READ_BUFFER",
+ "READ_FRAMEBUFFER",
+ "READ_FRAMEBUFFER_BINDING",
+ "READ_ONLY",
+ "READ_ONLY_ERR",
+ "READ_WRITE",
+ "RED",
+ "RED_BITS",
+ "RED_INTEGER",
+ "REMOVAL",
+ "RENDERBUFFER",
+ "RENDERBUFFER_ALPHA_SIZE",
+ "RENDERBUFFER_BINDING",
+ "RENDERBUFFER_BLUE_SIZE",
+ "RENDERBUFFER_DEPTH_SIZE",
+ "RENDERBUFFER_GREEN_SIZE",
+ "RENDERBUFFER_HEIGHT",
+ "RENDERBUFFER_INTERNAL_FORMAT",
+ "RENDERBUFFER_RED_SIZE",
+ "RENDERBUFFER_SAMPLES",
+ "RENDERBUFFER_STENCIL_SIZE",
+ "RENDERBUFFER_WIDTH",
+ "RENDERER",
+ "RENDERING_INTENT_ABSOLUTE_COLORIMETRIC",
+ "RENDERING_INTENT_AUTO",
+ "RENDERING_INTENT_PERCEPTUAL",
+ "RENDERING_INTENT_RELATIVE_COLORIMETRIC",
+ "RENDERING_INTENT_SATURATION",
+ "RENDERING_INTENT_UNKNOWN",
+ "REPEAT",
+ "REPLACE",
+ "RG",
+ "RG16F",
+ "RG16I",
+ "RG16UI",
+ "RG32F",
+ "RG32I",
+ "RG32UI",
+ "RG8",
+ "RG8I",
+ "RG8UI",
+ "RG8_SNORM",
+ "RGB",
+ "RGB10_A2",
+ "RGB10_A2UI",
+ "RGB16F",
+ "RGB16I",
+ "RGB16UI",
+ "RGB32F",
+ "RGB32I",
+ "RGB32UI",
+ "RGB565",
+ "RGB5_A1",
+ "RGB8",
+ "RGB8I",
+ "RGB8UI",
+ "RGB8_SNORM",
+ "RGB9_E5",
+ "RGBA",
+ "RGBA16F",
+ "RGBA16I",
+ "RGBA16UI",
+ "RGBA32F",
+ "RGBA32I",
+ "RGBA32UI",
+ "RGBA4",
+ "RGBA8",
+ "RGBA8I",
+ "RGBA8UI",
+ "RGBA8_SNORM",
+ "RGBA_INTEGER",
+ "RGBColor",
+ "RGB_INTEGER",
+ "RG_INTEGER",
+ "ROTATION_CLOCKWISE",
+ "ROTATION_COUNTERCLOCKWISE",
+ "RTCCertificate",
+ "RTCDTMFSender",
+ "RTCDTMFToneChangeEvent",
+ "RTCDataChannel",
+ "RTCDataChannelEvent",
+ "RTCDtlsTransport",
+ "RTCError",
+ "RTCErrorEvent",
+ "RTCIceCandidate",
+ "RTCIceTransport",
+ "RTCPeerConnection",
+ "RTCPeerConnectionIceErrorEvent",
+ "RTCPeerConnectionIceEvent",
+ "RTCRtpReceiver",
+ "RTCRtpSender",
+ "RTCRtpTransceiver",
+ "RTCSctpTransport",
+ "RTCSessionDescription",
+ "RTCStatsReport",
+ "RTCTrackEvent",
+ "RadioNodeList",
+ "Range",
+ "RangeError",
+ "RangeException",
+ "ReadableStream",
+ "ReadableStreamDefaultReader",
+ "RecordErrorEvent",
+ "Rect",
+ "ReferenceError",
+ "Reflect",
+ "RegExp",
+ "RelativeOrientationSensor",
+ "RelativeTimeFormat",
+ "RemotePlayback",
+ "Report",
+ "ReportBody",
+ "ReportingObserver",
+ "Request",
+ "ResizeObserver",
+ "ResizeObserverEntry",
+ "ResizeObserverSize",
+ "Response",
+ "RuntimeError",
+ "SAMPLER_2D",
+ "SAMPLER_2D_ARRAY",
+ "SAMPLER_2D_ARRAY_SHADOW",
+ "SAMPLER_2D_SHADOW",
+ "SAMPLER_3D",
+ "SAMPLER_BINDING",
+ "SAMPLER_CUBE",
+ "SAMPLER_CUBE_SHADOW",
+ "SAMPLES",
+ "SAMPLE_ALPHA_TO_COVERAGE",
+ "SAMPLE_BUFFERS",
+ "SAMPLE_COVERAGE",
+ "SAMPLE_COVERAGE_INVERT",
+ "SAMPLE_COVERAGE_VALUE",
+ "SAWTOOTH",
+ "SCHEDULED_STATE",
+ "SCISSOR_BOX",
+ "SCISSOR_TEST",
+ "SCROLL_PAGE_DOWN",
+ "SCROLL_PAGE_UP",
+ "SDP_ANSWER",
+ "SDP_OFFER",
+ "SDP_PRANSWER",
+ "SECURITY_ERR",
+ "SELECT",
+ "SEPARATE_ATTRIBS",
+ "SERIALIZE_ERR",
+ "SEVERITY_ERROR",
+ "SEVERITY_FATAL_ERROR",
+ "SEVERITY_WARNING",
+ "SHADER_COMPILER",
+ "SHADER_TYPE",
+ "SHADING_LANGUAGE_VERSION",
+ "SHIFT_MASK",
+ "SHORT",
+ "SHOWING",
+ "SHOW_ALL",
+ "SHOW_ATTRIBUTE",
+ "SHOW_CDATA_SECTION",
+ "SHOW_COMMENT",
+ "SHOW_DOCUMENT",
+ "SHOW_DOCUMENT_FRAGMENT",
+ "SHOW_DOCUMENT_TYPE",
+ "SHOW_ELEMENT",
+ "SHOW_ENTITY",
+ "SHOW_ENTITY_REFERENCE",
+ "SHOW_NOTATION",
+ "SHOW_PROCESSING_INSTRUCTION",
+ "SHOW_TEXT",
+ "SIGNALED",
+ "SIGNED_NORMALIZED",
+ "SINE",
+ "SOUNDFIELD",
+ "SQLException",
+ "SQRT1_2",
+ "SQRT2",
+ "SQUARE",
+ "SRC_ALPHA",
+ "SRC_ALPHA_SATURATE",
+ "SRC_COLOR",
+ "SRGB",
+ "SRGB8",
+ "SRGB8_ALPHA8",
+ "START_TO_END",
+ "START_TO_START",
+ "STATIC_COPY",
+ "STATIC_DRAW",
+ "STATIC_READ",
+ "STENCIL",
+ "STENCIL_ATTACHMENT",
+ "STENCIL_BACK_FAIL",
+ "STENCIL_BACK_FUNC",
+ "STENCIL_BACK_PASS_DEPTH_FAIL",
+ "STENCIL_BACK_PASS_DEPTH_PASS",
+ "STENCIL_BACK_REF",
+ "STENCIL_BACK_VALUE_MASK",
+ "STENCIL_BACK_WRITEMASK",
+ "STENCIL_BITS",
+ "STENCIL_BUFFER_BIT",
+ "STENCIL_CLEAR_VALUE",
+ "STENCIL_FAIL",
+ "STENCIL_FUNC",
+ "STENCIL_INDEX",
+ "STENCIL_INDEX8",
+ "STENCIL_PASS_DEPTH_FAIL",
+ "STENCIL_PASS_DEPTH_PASS",
+ "STENCIL_REF",
+ "STENCIL_TEST",
+ "STENCIL_VALUE_MASK",
+ "STENCIL_WRITEMASK",
+ "STREAM_COPY",
+ "STREAM_DRAW",
+ "STREAM_READ",
+ "STRING_TYPE",
+ "STYLE_RULE",
+ "SUBPIXEL_BITS",
+ "SUPPORTS_RULE",
+ "SVGAElement",
+ "SVGAltGlyphDefElement",
+ "SVGAltGlyphElement",
+ "SVGAltGlyphItemElement",
+ "SVGAngle",
+ "SVGAnimateColorElement",
+ "SVGAnimateElement",
+ "SVGAnimateMotionElement",
+ "SVGAnimateTransformElement",
+ "SVGAnimatedAngle",
+ "SVGAnimatedBoolean",
+ "SVGAnimatedEnumeration",
+ "SVGAnimatedInteger",
+ "SVGAnimatedLength",
+ "SVGAnimatedLengthList",
+ "SVGAnimatedNumber",
+ "SVGAnimatedNumberList",
+ "SVGAnimatedPreserveAspectRatio",
+ "SVGAnimatedRect",
+ "SVGAnimatedString",
+ "SVGAnimatedTransformList",
+ "SVGAnimationElement",
+ "SVGCircleElement",
+ "SVGClipPathElement",
+ "SVGColor",
+ "SVGComponentTransferFunctionElement",
+ "SVGCursorElement",
+ "SVGDefsElement",
+ "SVGDescElement",
+ "SVGDiscardElement",
+ "SVGDocument",
+ "SVGElement",
+ "SVGElementInstance",
+ "SVGElementInstanceList",
+ "SVGEllipseElement",
+ "SVGException",
+ "SVGFEBlendElement",
+ "SVGFEColorMatrixElement",
+ "SVGFEComponentTransferElement",
+ "SVGFECompositeElement",
+ "SVGFEConvolveMatrixElement",
+ "SVGFEDiffuseLightingElement",
+ "SVGFEDisplacementMapElement",
+ "SVGFEDistantLightElement",
+ "SVGFEDropShadowElement",
+ "SVGFEFloodElement",
+ "SVGFEFuncAElement",
+ "SVGFEFuncBElement",
+ "SVGFEFuncGElement",
+ "SVGFEFuncRElement",
+ "SVGFEGaussianBlurElement",
+ "SVGFEImageElement",
+ "SVGFEMergeElement",
+ "SVGFEMergeNodeElement",
+ "SVGFEMorphologyElement",
+ "SVGFEOffsetElement",
+ "SVGFEPointLightElement",
+ "SVGFESpecularLightingElement",
+ "SVGFESpotLightElement",
+ "SVGFETileElement",
+ "SVGFETurbulenceElement",
+ "SVGFilterElement",
+ "SVGFontElement",
+ "SVGFontFaceElement",
+ "SVGFontFaceFormatElement",
+ "SVGFontFaceNameElement",
+ "SVGFontFaceSrcElement",
+ "SVGFontFaceUriElement",
+ "SVGForeignObjectElement",
+ "SVGGElement",
+ "SVGGeometryElement",
+ "SVGGlyphElement",
+ "SVGGlyphRefElement",
+ "SVGGradientElement",
+ "SVGGraphicsElement",
+ "SVGHKernElement",
+ "SVGImageElement",
+ "SVGLength",
+ "SVGLengthList",
+ "SVGLineElement",
+ "SVGLinearGradientElement",
+ "SVGMPathElement",
+ "SVGMarkerElement",
+ "SVGMaskElement",
+ "SVGMatrix",
+ "SVGMetadataElement",
+ "SVGMissingGlyphElement",
+ "SVGNumber",
+ "SVGNumberList",
+ "SVGPaint",
+ "SVGPathElement",
+ "SVGPathSeg",
+ "SVGPathSegArcAbs",
+ "SVGPathSegArcRel",
+ "SVGPathSegClosePath",
+ "SVGPathSegCurvetoCubicAbs",
+ "SVGPathSegCurvetoCubicRel",
+ "SVGPathSegCurvetoCubicSmoothAbs",
+ "SVGPathSegCurvetoCubicSmoothRel",
+ "SVGPathSegCurvetoQuadraticAbs",
+ "SVGPathSegCurvetoQuadraticRel",
+ "SVGPathSegCurvetoQuadraticSmoothAbs",
+ "SVGPathSegCurvetoQuadraticSmoothRel",
+ "SVGPathSegLinetoAbs",
+ "SVGPathSegLinetoHorizontalAbs",
+ "SVGPathSegLinetoHorizontalRel",
+ "SVGPathSegLinetoRel",
+ "SVGPathSegLinetoVerticalAbs",
+ "SVGPathSegLinetoVerticalRel",
+ "SVGPathSegList",
+ "SVGPathSegMovetoAbs",
+ "SVGPathSegMovetoRel",
+ "SVGPatternElement",
+ "SVGPoint",
+ "SVGPointList",
+ "SVGPolygonElement",
+ "SVGPolylineElement",
+ "SVGPreserveAspectRatio",
+ "SVGRadialGradientElement",
+ "SVGRect",
+ "SVGRectElement",
+ "SVGRenderingIntent",
+ "SVGSVGElement",
+ "SVGScriptElement",
+ "SVGSetElement",
+ "SVGStopElement",
+ "SVGStringList",
+ "SVGStyleElement",
+ "SVGSwitchElement",
+ "SVGSymbolElement",
+ "SVGTRefElement",
+ "SVGTSpanElement",
+ "SVGTextContentElement",
+ "SVGTextElement",
+ "SVGTextPathElement",
+ "SVGTextPositioningElement",
+ "SVGTitleElement",
+ "SVGTransform",
+ "SVGTransformList",
+ "SVGUnitTypes",
+ "SVGUseElement",
+ "SVGVKernElement",
+ "SVGViewElement",
+ "SVGViewSpec",
+ "SVGZoomAndPan",
+ "SVGZoomEvent",
+ "SVG_ANGLETYPE_DEG",
+ "SVG_ANGLETYPE_GRAD",
+ "SVG_ANGLETYPE_RAD",
+ "SVG_ANGLETYPE_UNKNOWN",
+ "SVG_ANGLETYPE_UNSPECIFIED",
+ "SVG_CHANNEL_A",
+ "SVG_CHANNEL_B",
+ "SVG_CHANNEL_G",
+ "SVG_CHANNEL_R",
+ "SVG_CHANNEL_UNKNOWN",
+ "SVG_COLORTYPE_CURRENTCOLOR",
+ "SVG_COLORTYPE_RGBCOLOR",
+ "SVG_COLORTYPE_RGBCOLOR_ICCCOLOR",
+ "SVG_COLORTYPE_UNKNOWN",
+ "SVG_EDGEMODE_DUPLICATE",
+ "SVG_EDGEMODE_NONE",
+ "SVG_EDGEMODE_UNKNOWN",
+ "SVG_EDGEMODE_WRAP",
+ "SVG_FEBLEND_MODE_COLOR",
+ "SVG_FEBLEND_MODE_COLOR_BURN",
+ "SVG_FEBLEND_MODE_COLOR_DODGE",
+ "SVG_FEBLEND_MODE_DARKEN",
+ "SVG_FEBLEND_MODE_DIFFERENCE",
+ "SVG_FEBLEND_MODE_EXCLUSION",
+ "SVG_FEBLEND_MODE_HARD_LIGHT",
+ "SVG_FEBLEND_MODE_HUE",
+ "SVG_FEBLEND_MODE_LIGHTEN",
+ "SVG_FEBLEND_MODE_LUMINOSITY",
+ "SVG_FEBLEND_MODE_MULTIPLY",
+ "SVG_FEBLEND_MODE_NORMAL",
+ "SVG_FEBLEND_MODE_OVERLAY",
+ "SVG_FEBLEND_MODE_SATURATION",
+ "SVG_FEBLEND_MODE_SCREEN",
+ "SVG_FEBLEND_MODE_SOFT_LIGHT",
+ "SVG_FEBLEND_MODE_UNKNOWN",
+ "SVG_FECOLORMATRIX_TYPE_HUEROTATE",
+ "SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA",
+ "SVG_FECOLORMATRIX_TYPE_MATRIX",
+ "SVG_FECOLORMATRIX_TYPE_SATURATE",
+ "SVG_FECOLORMATRIX_TYPE_UNKNOWN",
+ "SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE",
+ "SVG_FECOMPONENTTRANSFER_TYPE_GAMMA",
+ "SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY",
+ "SVG_FECOMPONENTTRANSFER_TYPE_LINEAR",
+ "SVG_FECOMPONENTTRANSFER_TYPE_TABLE",
+ "SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN",
+ "SVG_FECOMPOSITE_OPERATOR_ARITHMETIC",
+ "SVG_FECOMPOSITE_OPERATOR_ATOP",
+ "SVG_FECOMPOSITE_OPERATOR_IN",
+ "SVG_FECOMPOSITE_OPERATOR_OUT",
+ "SVG_FECOMPOSITE_OPERATOR_OVER",
+ "SVG_FECOMPOSITE_OPERATOR_UNKNOWN",
+ "SVG_FECOMPOSITE_OPERATOR_XOR",
+ "SVG_INVALID_VALUE_ERR",
+ "SVG_LENGTHTYPE_CM",
+ "SVG_LENGTHTYPE_EMS",
+ "SVG_LENGTHTYPE_EXS",
+ "SVG_LENGTHTYPE_IN",
+ "SVG_LENGTHTYPE_MM",
+ "SVG_LENGTHTYPE_NUMBER",
+ "SVG_LENGTHTYPE_PC",
+ "SVG_LENGTHTYPE_PERCENTAGE",
+ "SVG_LENGTHTYPE_PT",
+ "SVG_LENGTHTYPE_PX",
+ "SVG_LENGTHTYPE_UNKNOWN",
+ "SVG_MARKERUNITS_STROKEWIDTH",
+ "SVG_MARKERUNITS_UNKNOWN",
+ "SVG_MARKERUNITS_USERSPACEONUSE",
+ "SVG_MARKER_ORIENT_ANGLE",
+ "SVG_MARKER_ORIENT_AUTO",
+ "SVG_MARKER_ORIENT_UNKNOWN",
+ "SVG_MASKTYPE_ALPHA",
+ "SVG_MASKTYPE_LUMINANCE",
+ "SVG_MATRIX_NOT_INVERTABLE",
+ "SVG_MEETORSLICE_MEET",
+ "SVG_MEETORSLICE_SLICE",
+ "SVG_MEETORSLICE_UNKNOWN",
+ "SVG_MORPHOLOGY_OPERATOR_DILATE",
+ "SVG_MORPHOLOGY_OPERATOR_ERODE",
+ "SVG_MORPHOLOGY_OPERATOR_UNKNOWN",
+ "SVG_PAINTTYPE_CURRENTCOLOR",
+ "SVG_PAINTTYPE_NONE",
+ "SVG_PAINTTYPE_RGBCOLOR",
+ "SVG_PAINTTYPE_RGBCOLOR_ICCCOLOR",
+ "SVG_PAINTTYPE_UNKNOWN",
+ "SVG_PAINTTYPE_URI",
+ "SVG_PAINTTYPE_URI_CURRENTCOLOR",
+ "SVG_PAINTTYPE_URI_NONE",
+ "SVG_PAINTTYPE_URI_RGBCOLOR",
+ "SVG_PAINTTYPE_URI_RGBCOLOR_ICCCOLOR",
+ "SVG_PRESERVEASPECTRATIO_NONE",
+ "SVG_PRESERVEASPECTRATIO_UNKNOWN",
+ "SVG_PRESERVEASPECTRATIO_XMAXYMAX",
+ "SVG_PRESERVEASPECTRATIO_XMAXYMID",
+ "SVG_PRESERVEASPECTRATIO_XMAXYMIN",
+ "SVG_PRESERVEASPECTRATIO_XMIDYMAX",
+ "SVG_PRESERVEASPECTRATIO_XMIDYMID",
+ "SVG_PRESERVEASPECTRATIO_XMIDYMIN",
+ "SVG_PRESERVEASPECTRATIO_XMINYMAX",
+ "SVG_PRESERVEASPECTRATIO_XMINYMID",
+ "SVG_PRESERVEASPECTRATIO_XMINYMIN",
+ "SVG_SPREADMETHOD_PAD",
+ "SVG_SPREADMETHOD_REFLECT",
+ "SVG_SPREADMETHOD_REPEAT",
+ "SVG_SPREADMETHOD_UNKNOWN",
+ "SVG_STITCHTYPE_NOSTITCH",
+ "SVG_STITCHTYPE_STITCH",
+ "SVG_STITCHTYPE_UNKNOWN",
+ "SVG_TRANSFORM_MATRIX",
+ "SVG_TRANSFORM_ROTATE",
+ "SVG_TRANSFORM_SCALE",
+ "SVG_TRANSFORM_SKEWX",
+ "SVG_TRANSFORM_SKEWY",
+ "SVG_TRANSFORM_TRANSLATE",
+ "SVG_TRANSFORM_UNKNOWN",
+ "SVG_TURBULENCE_TYPE_FRACTALNOISE",
+ "SVG_TURBULENCE_TYPE_TURBULENCE",
+ "SVG_TURBULENCE_TYPE_UNKNOWN",
+ "SVG_UNIT_TYPE_OBJECTBOUNDINGBOX",
+ "SVG_UNIT_TYPE_UNKNOWN",
+ "SVG_UNIT_TYPE_USERSPACEONUSE",
+ "SVG_WRONG_TYPE_ERR",
+ "SVG_ZOOMANDPAN_DISABLE",
+ "SVG_ZOOMANDPAN_MAGNIFY",
+ "SVG_ZOOMANDPAN_UNKNOWN",
+ "SYNC_CONDITION",
+ "SYNC_FENCE",
+ "SYNC_FLAGS",
+ "SYNC_FLUSH_COMMANDS_BIT",
+ "SYNC_GPU_COMMANDS_COMPLETE",
+ "SYNC_STATUS",
+ "SYNTAX_ERR",
+ "SavedPages",
+ "Screen",
+ "ScreenOrientation",
+ "Script",
+ "ScriptProcessorNode",
+ "ScrollAreaEvent",
+ "SecurityPolicyViolationEvent",
+ "Selection",
+ "Sensor",
+ "SensorErrorEvent",
+ "ServiceWorker",
+ "ServiceWorkerContainer",
+ "ServiceWorkerRegistration",
+ "SessionDescription",
+ "Set",
+ "ShadowRoot",
+ "SharedArrayBuffer",
+ "SharedWorker",
+ "SimpleGestureEvent",
+ "SourceBuffer",
+ "SourceBufferList",
+ "SpeechSynthesis",
+ "SpeechSynthesisErrorEvent",
+ "SpeechSynthesisEvent",
+ "SpeechSynthesisUtterance",
+ "SpeechSynthesisVoice",
+ "StaticRange",
+ "StereoPannerNode",
+ "StopIteration",
+ "Storage",
+ "StorageEvent",
+ "StorageManager",
+ "String",
+ "StructType",
+ "StylePropertyMap",
+ "StylePropertyMapReadOnly",
+ "StyleSheet",
+ "StyleSheetList",
+ "SubmitEvent",
+ "SubtleCrypto",
+ "Symbol",
+ "SyncManager",
+ "SyntaxError",
+ "TEMPORARY",
+ "TEXTPATH_METHODTYPE_ALIGN",
+ "TEXTPATH_METHODTYPE_STRETCH",
+ "TEXTPATH_METHODTYPE_UNKNOWN",
+ "TEXTPATH_SPACINGTYPE_AUTO",
+ "TEXTPATH_SPACINGTYPE_EXACT",
+ "TEXTPATH_SPACINGTYPE_UNKNOWN",
+ "TEXTURE",
+ "TEXTURE0",
+ "TEXTURE1",
+ "TEXTURE10",
+ "TEXTURE11",
+ "TEXTURE12",
+ "TEXTURE13",
+ "TEXTURE14",
+ "TEXTURE15",
+ "TEXTURE16",
+ "TEXTURE17",
+ "TEXTURE18",
+ "TEXTURE19",
+ "TEXTURE2",
+ "TEXTURE20",
+ "TEXTURE21",
+ "TEXTURE22",
+ "TEXTURE23",
+ "TEXTURE24",
+ "TEXTURE25",
+ "TEXTURE26",
+ "TEXTURE27",
+ "TEXTURE28",
+ "TEXTURE29",
+ "TEXTURE3",
+ "TEXTURE30",
+ "TEXTURE31",
+ "TEXTURE4",
+ "TEXTURE5",
+ "TEXTURE6",
+ "TEXTURE7",
+ "TEXTURE8",
+ "TEXTURE9",
+ "TEXTURE_2D",
+ "TEXTURE_2D_ARRAY",
+ "TEXTURE_3D",
+ "TEXTURE_BASE_LEVEL",
+ "TEXTURE_BINDING_2D",
+ "TEXTURE_BINDING_2D_ARRAY",
+ "TEXTURE_BINDING_3D",
+ "TEXTURE_BINDING_CUBE_MAP",
+ "TEXTURE_COMPARE_FUNC",
+ "TEXTURE_COMPARE_MODE",
+ "TEXTURE_CUBE_MAP",
+ "TEXTURE_CUBE_MAP_NEGATIVE_X",
+ "TEXTURE_CUBE_MAP_NEGATIVE_Y",
+ "TEXTURE_CUBE_MAP_NEGATIVE_Z",
+ "TEXTURE_CUBE_MAP_POSITIVE_X",
+ "TEXTURE_CUBE_MAP_POSITIVE_Y",
+ "TEXTURE_CUBE_MAP_POSITIVE_Z",
+ "TEXTURE_IMMUTABLE_FORMAT",
+ "TEXTURE_IMMUTABLE_LEVELS",
+ "TEXTURE_MAG_FILTER",
+ "TEXTURE_MAX_ANISOTROPY_EXT",
+ "TEXTURE_MAX_LEVEL",
+ "TEXTURE_MAX_LOD",
+ "TEXTURE_MIN_FILTER",
+ "TEXTURE_MIN_LOD",
+ "TEXTURE_WRAP_R",
+ "TEXTURE_WRAP_S",
+ "TEXTURE_WRAP_T",
+ "TEXT_NODE",
+ "TIMEOUT",
+ "TIMEOUT_ERR",
+ "TIMEOUT_EXPIRED",
+ "TIMEOUT_IGNORED",
+ "TOO_LARGE_ERR",
+ "TRANSACTION_INACTIVE_ERR",
+ "TRANSFORM_FEEDBACK",
+ "TRANSFORM_FEEDBACK_ACTIVE",
+ "TRANSFORM_FEEDBACK_BINDING",
+ "TRANSFORM_FEEDBACK_BUFFER",
+ "TRANSFORM_FEEDBACK_BUFFER_BINDING",
+ "TRANSFORM_FEEDBACK_BUFFER_MODE",
+ "TRANSFORM_FEEDBACK_BUFFER_SIZE",
+ "TRANSFORM_FEEDBACK_BUFFER_START",
+ "TRANSFORM_FEEDBACK_PAUSED",
+ "TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN",
+ "TRANSFORM_FEEDBACK_VARYINGS",
+ "TRIANGLE",
+ "TRIANGLES",
+ "TRIANGLE_FAN",
+ "TRIANGLE_STRIP",
+ "TYPE_BACK_FORWARD",
+ "TYPE_ERR",
+ "TYPE_MISMATCH_ERR",
+ "TYPE_NAVIGATE",
+ "TYPE_RELOAD",
+ "TYPE_RESERVED",
+ "Table",
+ "TaskAttributionTiming",
+ "Text",
+ "TextDecoder",
+ "TextDecoderStream",
+ "TextEncoder",
+ "TextEncoderStream",
+ "TextEvent",
+ "TextMetrics",
+ "TextTrack",
+ "TextTrackCue",
+ "TextTrackCueList",
+ "TextTrackList",
+ "TimeEvent",
+ "TimeRanges",
+ "Touch",
+ "TouchEvent",
+ "TouchList",
+ "TrackEvent",
+ "TransformStream",
+ "TransitionEvent",
+ "TreeWalker",
+ "TrustedHTML",
+ "TrustedScript",
+ "TrustedScriptURL",
+ "TrustedTypePolicy",
+ "TrustedTypePolicyFactory",
+ "TypeError",
+ "TypedObject",
+ "U2F",
+ "UIEvent",
+ "UNCACHED",
+ "UNIFORM_ARRAY_STRIDE",
+ "UNIFORM_BLOCK_ACTIVE_UNIFORMS",
+ "UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES",
+ "UNIFORM_BLOCK_BINDING",
+ "UNIFORM_BLOCK_DATA_SIZE",
+ "UNIFORM_BLOCK_INDEX",
+ "UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER",
+ "UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER",
+ "UNIFORM_BUFFER",
+ "UNIFORM_BUFFER_BINDING",
+ "UNIFORM_BUFFER_OFFSET_ALIGNMENT",
+ "UNIFORM_BUFFER_SIZE",
+ "UNIFORM_BUFFER_START",
+ "UNIFORM_IS_ROW_MAJOR",
+ "UNIFORM_MATRIX_STRIDE",
+ "UNIFORM_OFFSET",
+ "UNIFORM_SIZE",
+ "UNIFORM_TYPE",
+ "UNKNOWN_ERR",
+ "UNKNOWN_RULE",
+ "UNMASKED_RENDERER_WEBGL",
+ "UNMASKED_VENDOR_WEBGL",
+ "UNORDERED_NODE_ITERATOR_TYPE",
+ "UNORDERED_NODE_SNAPSHOT_TYPE",
+ "UNPACK_ALIGNMENT",
+ "UNPACK_COLORSPACE_CONVERSION_WEBGL",
+ "UNPACK_FLIP_Y_WEBGL",
+ "UNPACK_IMAGE_HEIGHT",
+ "UNPACK_PREMULTIPLY_ALPHA_WEBGL",
+ "UNPACK_ROW_LENGTH",
+ "UNPACK_SKIP_IMAGES",
+ "UNPACK_SKIP_PIXELS",
+ "UNPACK_SKIP_ROWS",
+ "UNSCHEDULED_STATE",
+ "UNSENT",
+ "UNSIGNALED",
+ "UNSIGNED_BYTE",
+ "UNSIGNED_INT",
+ "UNSIGNED_INT_10F_11F_11F_REV",
+ "UNSIGNED_INT_24_8",
+ "UNSIGNED_INT_2_10_10_10_REV",
+ "UNSIGNED_INT_5_9_9_9_REV",
+ "UNSIGNED_INT_SAMPLER_2D",
+ "UNSIGNED_INT_SAMPLER_2D_ARRAY",
+ "UNSIGNED_INT_SAMPLER_3D",
+ "UNSIGNED_INT_SAMPLER_CUBE",
+ "UNSIGNED_INT_VEC2",
+ "UNSIGNED_INT_VEC3",
+ "UNSIGNED_INT_VEC4",
+ "UNSIGNED_NORMALIZED",
+ "UNSIGNED_SHORT",
+ "UNSIGNED_SHORT_4_4_4_4",
+ "UNSIGNED_SHORT_5_5_5_1",
+ "UNSIGNED_SHORT_5_6_5",
+ "UNSPECIFIED_EVENT_TYPE_ERR",
+ "UPDATEREADY",
+ "URIError",
+ "URL",
+ "URLSearchParams",
+ "URLUnencoded",
+ "URL_MISMATCH_ERR",
+ "USB",
+ "USBAlternateInterface",
+ "USBConfiguration",
+ "USBConnectionEvent",
+ "USBDevice",
+ "USBEndpoint",
+ "USBInTransferResult",
+ "USBInterface",
+ "USBIsochronousInTransferPacket",
+ "USBIsochronousInTransferResult",
+ "USBIsochronousOutTransferPacket",
+ "USBIsochronousOutTransferResult",
+ "USBOutTransferResult",
+ "UTC",
+ "Uint16Array",
+ "Uint32Array",
+ "Uint8Array",
+ "Uint8ClampedArray",
+ "UserActivation",
+ "UserMessageHandler",
+ "UserMessageHandlersNamespace",
+ "UserProximityEvent",
+ "VALIDATE_STATUS",
+ "VALIDATION_ERR",
+ "VARIABLES_RULE",
+ "VENDOR",
+ "VERSION",
+ "VERSION_CHANGE",
+ "VERSION_ERR",
+ "VERTEX_ARRAY_BINDING",
+ "VERTEX_ATTRIB_ARRAY_BUFFER_BINDING",
+ "VERTEX_ATTRIB_ARRAY_DIVISOR",
+ "VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE",
+ "VERTEX_ATTRIB_ARRAY_ENABLED",
+ "VERTEX_ATTRIB_ARRAY_INTEGER",
+ "VERTEX_ATTRIB_ARRAY_NORMALIZED",
+ "VERTEX_ATTRIB_ARRAY_POINTER",
+ "VERTEX_ATTRIB_ARRAY_SIZE",
+ "VERTEX_ATTRIB_ARRAY_STRIDE",
+ "VERTEX_ATTRIB_ARRAY_TYPE",
+ "VERTEX_SHADER",
+ "VERTICAL",
+ "VERTICAL_AXIS",
+ "VER_ERR",
+ "VIEWPORT",
+ "VIEWPORT_RULE",
+ "VRDisplay",
+ "VRDisplayCapabilities",
+ "VRDisplayEvent",
+ "VREyeParameters",
+ "VRFieldOfView",
+ "VRFrameData",
+ "VRPose",
+ "VRStageParameters",
+ "VTTCue",
+ "VTTRegion",
+ "ValidityState",
+ "VideoPlaybackQuality",
+ "VideoStreamTrack",
+ "VisualViewport",
+ "WAIT_FAILED",
+ "WEBKIT_FILTER_RULE",
+ "WEBKIT_KEYFRAMES_RULE",
+ "WEBKIT_KEYFRAME_RULE",
+ "WEBKIT_REGION_RULE",
+ "WRONG_DOCUMENT_ERR",
+ "WakeLock",
+ "WakeLockSentinel",
+ "WasmAnyRef",
+ "WaveShaperNode",
+ "WeakMap",
+ "WeakRef",
+ "WeakSet",
+ "WebAssembly",
+ "WebGL2RenderingContext",
+ "WebGLActiveInfo",
+ "WebGLBuffer",
+ "WebGLContextEvent",
+ "WebGLFramebuffer",
+ "WebGLProgram",
+ "WebGLQuery",
+ "WebGLRenderbuffer",
+ "WebGLRenderingContext",
+ "WebGLSampler",
+ "WebGLShader",
+ "WebGLShaderPrecisionFormat",
+ "WebGLSync",
+ "WebGLTexture",
+ "WebGLTransformFeedback",
+ "WebGLUniformLocation",
+ "WebGLVertexArray",
+ "WebGLVertexArrayObject",
+ "WebKitAnimationEvent",
+ "WebKitBlobBuilder",
+ "WebKitCSSFilterRule",
+ "WebKitCSSFilterValue",
+ "WebKitCSSKeyframeRule",
+ "WebKitCSSKeyframesRule",
+ "WebKitCSSMatrix",
+ "WebKitCSSRegionRule",
+ "WebKitCSSTransformValue",
+ "WebKitDataCue",
+ "WebKitGamepad",
+ "WebKitMediaKeyError",
+ "WebKitMediaKeyMessageEvent",
+ "WebKitMediaKeySession",
+ "WebKitMediaKeys",
+ "WebKitMediaSource",
+ "WebKitMutationObserver",
+ "WebKitNamespace",
+ "WebKitPlaybackTargetAvailabilityEvent",
+ "WebKitPoint",
+ "WebKitShadowRoot",
+ "WebKitSourceBuffer",
+ "WebKitSourceBufferList",
+ "WebKitTransitionEvent",
+ "WebSocket",
+ "WebkitAlignContent",
+ "WebkitAlignItems",
+ "WebkitAlignSelf",
+ "WebkitAnimation",
+ "WebkitAnimationDelay",
+ "WebkitAnimationDirection",
+ "WebkitAnimationDuration",
+ "WebkitAnimationFillMode",
+ "WebkitAnimationIterationCount",
+ "WebkitAnimationName",
+ "WebkitAnimationPlayState",
+ "WebkitAnimationTimingFunction",
+ "WebkitAppearance",
+ "WebkitBackfaceVisibility",
+ "WebkitBackgroundClip",
+ "WebkitBackgroundOrigin",
+ "WebkitBackgroundSize",
+ "WebkitBorderBottomLeftRadius",
+ "WebkitBorderBottomRightRadius",
+ "WebkitBorderImage",
+ "WebkitBorderRadius",
+ "WebkitBorderTopLeftRadius",
+ "WebkitBorderTopRightRadius",
+ "WebkitBoxAlign",
+ "WebkitBoxDirection",
+ "WebkitBoxFlex",
+ "WebkitBoxOrdinalGroup",
+ "WebkitBoxOrient",
+ "WebkitBoxPack",
+ "WebkitBoxShadow",
+ "WebkitBoxSizing",
+ "WebkitFilter",
+ "WebkitFlex",
+ "WebkitFlexBasis",
+ "WebkitFlexDirection",
+ "WebkitFlexFlow",
+ "WebkitFlexGrow",
+ "WebkitFlexShrink",
+ "WebkitFlexWrap",
+ "WebkitJustifyContent",
+ "WebkitLineClamp",
+ "WebkitMask",
+ "WebkitMaskClip",
+ "WebkitMaskComposite",
+ "WebkitMaskImage",
+ "WebkitMaskOrigin",
+ "WebkitMaskPosition",
+ "WebkitMaskPositionX",
+ "WebkitMaskPositionY",
+ "WebkitMaskRepeat",
+ "WebkitMaskSize",
+ "WebkitOrder",
+ "WebkitPerspective",
+ "WebkitPerspectiveOrigin",
+ "WebkitTextFillColor",
+ "WebkitTextSizeAdjust",
+ "WebkitTextStroke",
+ "WebkitTextStrokeColor",
+ "WebkitTextStrokeWidth",
+ "WebkitTransform",
+ "WebkitTransformOrigin",
+ "WebkitTransformStyle",
+ "WebkitTransition",
+ "WebkitTransitionDelay",
+ "WebkitTransitionDuration",
+ "WebkitTransitionProperty",
+ "WebkitTransitionTimingFunction",
+ "WebkitUserSelect",
+ "WheelEvent",
+ "Window",
+ "Worker",
+ "Worklet",
+ "WritableStream",
+ "WritableStreamDefaultWriter",
+ "XMLDocument",
+ "XMLHttpRequest",
+ "XMLHttpRequestEventTarget",
+ "XMLHttpRequestException",
+ "XMLHttpRequestProgressEvent",
+ "XMLHttpRequestUpload",
+ "XMLSerializer",
+ "XMLStylesheetProcessingInstruction",
+ "XPathEvaluator",
+ "XPathException",
+ "XPathExpression",
+ "XPathNSResolver",
+ "XPathResult",
+ "XRBoundedReferenceSpace",
+ "XRDOMOverlayState",
+ "XRFrame",
+ "XRHitTestResult",
+ "XRHitTestSource",
+ "XRInputSource",
+ "XRInputSourceArray",
+ "XRInputSourceEvent",
+ "XRInputSourcesChangeEvent",
+ "XRLayer",
+ "XRPose",
+ "XRRay",
+ "XRReferenceSpace",
+ "XRReferenceSpaceEvent",
+ "XRRenderState",
+ "XRRigidTransform",
+ "XRSession",
+ "XRSessionEvent",
+ "XRSpace",
+ "XRSystem",
+ "XRTransientInputHitTestResult",
+ "XRTransientInputHitTestSource",
+ "XRView",
+ "XRViewerPose",
+ "XRViewport",
+ "XRWebGLLayer",
+ "XSLTProcessor",
+ "ZERO",
+ "_XD0M_",
+ "_YD0M_",
+ "__defineGetter__",
+ "__defineSetter__",
+ "__lookupGetter__",
+ "__lookupSetter__",
+ "__opera",
+ "__proto__",
+ "_browserjsran",
+ "a",
+ "aLink",
+ "abbr",
+ "abort",
+ "aborted",
+ "abs",
+ "absolute",
+ "acceleration",
+ "accelerationIncludingGravity",
+ "accelerator",
+ "accept",
+ "acceptCharset",
+ "acceptNode",
+ "accessKey",
+ "accessKeyLabel",
+ "accuracy",
+ "acos",
+ "acosh",
+ "action",
+ "actionURL",
+ "actions",
+ "activated",
+ "active",
+ "activeCues",
+ "activeElement",
+ "activeSourceBuffers",
+ "activeSourceCount",
+ "activeTexture",
+ "activeVRDisplays",
+ "actualBoundingBoxAscent",
+ "actualBoundingBoxDescent",
+ "actualBoundingBoxLeft",
+ "actualBoundingBoxRight",
+ "add",
+ "addAll",
+ "addBehavior",
+ "addCandidate",
+ "addColorStop",
+ "addCue",
+ "addElement",
+ "addEventListener",
+ "addFilter",
+ "addFromString",
+ "addFromUri",
+ "addIceCandidate",
+ "addImport",
+ "addListener",
+ "addModule",
+ "addNamed",
+ "addPageRule",
+ "addPath",
+ "addPointer",
+ "addRange",
+ "addRegion",
+ "addRule",
+ "addSearchEngine",
+ "addSourceBuffer",
+ "addStream",
+ "addTextTrack",
+ "addTrack",
+ "addTransceiver",
+ "addWakeLockListener",
+ "added",
+ "addedNodes",
+ "additionalName",
+ "additiveSymbols",
+ "addons",
+ "address",
+ "addressLine",
+ "adoptNode",
+ "adoptedStyleSheets",
+ "adr",
+ "advance",
+ "after",
+ "album",
+ "alert",
+ "algorithm",
+ "align",
+ "align-content",
+ "align-items",
+ "align-self",
+ "alignContent",
+ "alignItems",
+ "alignSelf",
+ "alignmentBaseline",
+ "alinkColor",
+ "all",
+ "allSettled",
+ "allow",
+ "allowFullscreen",
+ "allowPaymentRequest",
+ "allowedDirections",
+ "allowedFeatures",
+ "allowedToPlay",
+ "allowsFeature",
+ "alpha",
+ "alt",
+ "altGraphKey",
+ "altHtml",
+ "altKey",
+ "altLeft",
+ "alternate",
+ "alternateSetting",
+ "alternates",
+ "altitude",
+ "altitudeAccuracy",
+ "amplitude",
+ "ancestorOrigins",
+ "anchor",
+ "anchorNode",
+ "anchorOffset",
+ "anchors",
+ "and",
+ "angle",
+ "angularAcceleration",
+ "angularVelocity",
+ "animVal",
+ "animate",
+ "animatedInstanceRoot",
+ "animatedNormalizedPathSegList",
+ "animatedPathSegList",
+ "animatedPoints",
+ "animation",
+ "animation-delay",
+ "animation-direction",
+ "animation-duration",
+ "animation-fill-mode",
+ "animation-iteration-count",
+ "animation-name",
+ "animation-play-state",
+ "animation-timing-function",
+ "animationDelay",
+ "animationDirection",
+ "animationDuration",
+ "animationFillMode",
+ "animationIterationCount",
+ "animationName",
+ "animationPlayState",
+ "animationStartTime",
+ "animationTimingFunction",
+ "animationsPaused",
+ "anniversary",
+ "antialias",
+ "anticipatedRemoval",
+ "any",
+ "app",
+ "appCodeName",
+ "appMinorVersion",
+ "appName",
+ "appNotifications",
+ "appVersion",
+ "appearance",
+ "append",
+ "appendBuffer",
+ "appendChild",
+ "appendData",
+ "appendItem",
+ "appendMedium",
+ "appendNamed",
+ "appendRule",
+ "appendStream",
+ "appendWindowEnd",
+ "appendWindowStart",
+ "applets",
+ "applicationCache",
+ "applicationServerKey",
+ "apply",
+ "applyConstraints",
+ "applyElement",
+ "arc",
+ "arcTo",
+ "archive",
+ "areas",
+ "arguments",
+ "ariaAtomic",
+ "ariaAutoComplete",
+ "ariaBusy",
+ "ariaChecked",
+ "ariaColCount",
+ "ariaColIndex",
+ "ariaColSpan",
+ "ariaCurrent",
+ "ariaDescription",
+ "ariaDisabled",
+ "ariaExpanded",
+ "ariaHasPopup",
+ "ariaHidden",
+ "ariaKeyShortcuts",
+ "ariaLabel",
+ "ariaLevel",
+ "ariaLive",
+ "ariaModal",
+ "ariaMultiLine",
+ "ariaMultiSelectable",
+ "ariaOrientation",
+ "ariaPlaceholder",
+ "ariaPosInSet",
+ "ariaPressed",
+ "ariaReadOnly",
+ "ariaRelevant",
+ "ariaRequired",
+ "ariaRoleDescription",
+ "ariaRowCount",
+ "ariaRowIndex",
+ "ariaRowSpan",
+ "ariaSelected",
+ "ariaSetSize",
+ "ariaSort",
+ "ariaValueMax",
+ "ariaValueMin",
+ "ariaValueNow",
+ "ariaValueText",
+ "arrayBuffer",
+ "artist",
+ "artwork",
+ "as",
+ "asIntN",
+ "asUintN",
+ "asin",
+ "asinh",
+ "assert",
+ "assign",
+ "assignedElements",
+ "assignedNodes",
+ "assignedSlot",
+ "async",
+ "asyncIterator",
+ "atEnd",
+ "atan",
+ "atan2",
+ "atanh",
+ "atob",
+ "attachEvent",
+ "attachInternals",
+ "attachShader",
+ "attachShadow",
+ "attachments",
+ "attack",
+ "attestationObject",
+ "attrChange",
+ "attrName",
+ "attributeFilter",
+ "attributeName",
+ "attributeNamespace",
+ "attributeOldValue",
+ "attributeStyleMap",
+ "attributes",
+ "attribution",
+ "audioBitsPerSecond",
+ "audioTracks",
+ "audioWorklet",
+ "authenticatedSignedWrites",
+ "authenticatorData",
+ "autoIncrement",
+ "autobuffer",
+ "autocapitalize",
+ "autocomplete",
+ "autocorrect",
+ "autofocus",
+ "automationRate",
+ "autoplay",
+ "availHeight",
+ "availLeft",
+ "availTop",
+ "availWidth",
+ "availability",
+ "available",
+ "aversion",
+ "ax",
+ "axes",
+ "axis",
+ "ay",
+ "azimuth",
+ "b",
+ "back",
+ "backface-visibility",
+ "backfaceVisibility",
+ "background",
+ "background-attachment",
+ "background-blend-mode",
+ "background-clip",
+ "background-color",
+ "background-image",
+ "background-origin",
+ "background-position",
+ "background-position-x",
+ "background-position-y",
+ "background-repeat",
+ "background-size",
+ "backgroundAttachment",
+ "backgroundBlendMode",
+ "backgroundClip",
+ "backgroundColor",
+ "backgroundFetch",
+ "backgroundImage",
+ "backgroundOrigin",
+ "backgroundPosition",
+ "backgroundPositionX",
+ "backgroundPositionY",
+ "backgroundRepeat",
+ "backgroundSize",
+ "badInput",
+ "badge",
+ "balance",
+ "baseFrequencyX",
+ "baseFrequencyY",
+ "baseLatency",
+ "baseLayer",
+ "baseNode",
+ "baseOffset",
+ "baseURI",
+ "baseVal",
+ "baselineShift",
+ "battery",
+ "bday",
+ "before",
+ "beginElement",
+ "beginElementAt",
+ "beginPath",
+ "beginQuery",
+ "beginTransformFeedback",
+ "behavior",
+ "behaviorCookie",
+ "behaviorPart",
+ "behaviorUrns",
+ "beta",
+ "bezierCurveTo",
+ "bgColor",
+ "bgProperties",
+ "bias",
+ "big",
+ "bigint64",
+ "biguint64",
+ "binaryType",
+ "bind",
+ "bindAttribLocation",
+ "bindBuffer",
+ "bindBufferBase",
+ "bindBufferRange",
+ "bindFramebuffer",
+ "bindRenderbuffer",
+ "bindSampler",
+ "bindTexture",
+ "bindTransformFeedback",
+ "bindVertexArray",
+ "blendColor",
+ "blendEquation",
+ "blendEquationSeparate",
+ "blendFunc",
+ "blendFuncSeparate",
+ "blink",
+ "blitFramebuffer",
+ "blob",
+ "block-size",
+ "blockDirection",
+ "blockSize",
+ "blockedURI",
+ "blue",
+ "bluetooth",
+ "blur",
+ "body",
+ "bodyUsed",
+ "bold",
+ "bookmarks",
+ "booleanValue",
+ "border",
+ "border-block",
+ "border-block-color",
+ "border-block-end",
+ "border-block-end-color",
+ "border-block-end-style",
+ "border-block-end-width",
+ "border-block-start",
+ "border-block-start-color",
+ "border-block-start-style",
+ "border-block-start-width",
+ "border-block-style",
+ "border-block-width",
+ "border-bottom",
+ "border-bottom-color",
+ "border-bottom-left-radius",
+ "border-bottom-right-radius",
+ "border-bottom-style",
+ "border-bottom-width",
+ "border-collapse",
+ "border-color",
+ "border-end-end-radius",
+ "border-end-start-radius",
+ "border-image",
+ "border-image-outset",
+ "border-image-repeat",
+ "border-image-slice",
+ "border-image-source",
+ "border-image-width",
+ "border-inline",
+ "border-inline-color",
+ "border-inline-end",
+ "border-inline-end-color",
+ "border-inline-end-style",
+ "border-inline-end-width",
+ "border-inline-start",
+ "border-inline-start-color",
+ "border-inline-start-style",
+ "border-inline-start-width",
+ "border-inline-style",
+ "border-inline-width",
+ "border-left",
+ "border-left-color",
+ "border-left-style",
+ "border-left-width",
+ "border-radius",
+ "border-right",
+ "border-right-color",
+ "border-right-style",
+ "border-right-width",
+ "border-spacing",
+ "border-start-end-radius",
+ "border-start-start-radius",
+ "border-style",
+ "border-top",
+ "border-top-color",
+ "border-top-left-radius",
+ "border-top-right-radius",
+ "border-top-style",
+ "border-top-width",
+ "border-width",
+ "borderBlock",
+ "borderBlockColor",
+ "borderBlockEnd",
+ "borderBlockEndColor",
+ "borderBlockEndStyle",
+ "borderBlockEndWidth",
+ "borderBlockStart",
+ "borderBlockStartColor",
+ "borderBlockStartStyle",
+ "borderBlockStartWidth",
+ "borderBlockStyle",
+ "borderBlockWidth",
+ "borderBottom",
+ "borderBottomColor",
+ "borderBottomLeftRadius",
+ "borderBottomRightRadius",
+ "borderBottomStyle",
+ "borderBottomWidth",
+ "borderBoxSize",
+ "borderCollapse",
+ "borderColor",
+ "borderColorDark",
+ "borderColorLight",
+ "borderEndEndRadius",
+ "borderEndStartRadius",
+ "borderImage",
+ "borderImageOutset",
+ "borderImageRepeat",
+ "borderImageSlice",
+ "borderImageSource",
+ "borderImageWidth",
+ "borderInline",
+ "borderInlineColor",
+ "borderInlineEnd",
+ "borderInlineEndColor",
+ "borderInlineEndStyle",
+ "borderInlineEndWidth",
+ "borderInlineStart",
+ "borderInlineStartColor",
+ "borderInlineStartStyle",
+ "borderInlineStartWidth",
+ "borderInlineStyle",
+ "borderInlineWidth",
+ "borderLeft",
+ "borderLeftColor",
+ "borderLeftStyle",
+ "borderLeftWidth",
+ "borderRadius",
+ "borderRight",
+ "borderRightColor",
+ "borderRightStyle",
+ "borderRightWidth",
+ "borderSpacing",
+ "borderStartEndRadius",
+ "borderStartStartRadius",
+ "borderStyle",
+ "borderTop",
+ "borderTopColor",
+ "borderTopLeftRadius",
+ "borderTopRightRadius",
+ "borderTopStyle",
+ "borderTopWidth",
+ "borderWidth",
+ "bottom",
+ "bottomMargin",
+ "bound",
+ "boundElements",
+ "boundingClientRect",
+ "boundingHeight",
+ "boundingLeft",
+ "boundingTop",
+ "boundingWidth",
+ "bounds",
+ "boundsGeometry",
+ "box-decoration-break",
+ "box-shadow",
+ "box-sizing",
+ "boxDecorationBreak",
+ "boxShadow",
+ "boxSizing",
+ "break-after",
+ "break-before",
+ "break-inside",
+ "breakAfter",
+ "breakBefore",
+ "breakInside",
+ "broadcast",
+ "browserLanguage",
+ "btoa",
+ "bubbles",
+ "buffer",
+ "bufferData",
+ "bufferDepth",
+ "bufferSize",
+ "bufferSubData",
+ "buffered",
+ "bufferedAmount",
+ "bufferedAmountLowThreshold",
+ "buildID",
+ "buildNumber",
+ "button",
+ "buttonID",
+ "buttons",
+ "byteLength",
+ "byteOffset",
+ "bytesWritten",
+ "c",
+ "cache",
+ "caches",
+ "call",
+ "caller",
+ "canBeFormatted",
+ "canBeMounted",
+ "canBeShared",
+ "canHaveChildren",
+ "canHaveHTML",
+ "canInsertDTMF",
+ "canMakePayment",
+ "canPlayType",
+ "canPresent",
+ "canTrickleIceCandidates",
+ "cancel",
+ "cancelAndHoldAtTime",
+ "cancelAnimationFrame",
+ "cancelBubble",
+ "cancelIdleCallback",
+ "cancelScheduledValues",
+ "cancelVideoFrameCallback",
+ "cancelWatchAvailability",
+ "cancelable",
+ "candidate",
+ "canonicalUUID",
+ "canvas",
+ "capabilities",
+ "caption",
+ "caption-side",
+ "captionSide",
+ "capture",
+ "captureEvents",
+ "captureStackTrace",
+ "captureStream",
+ "caret-color",
+ "caretBidiLevel",
+ "caretColor",
+ "caretPositionFromPoint",
+ "caretRangeFromPoint",
+ "cast",
+ "catch",
+ "category",
+ "cbrt",
+ "cd",
+ "ceil",
+ "cellIndex",
+ "cellPadding",
+ "cellSpacing",
+ "cells",
+ "ch",
+ "chOff",
+ "chain",
+ "challenge",
+ "changeType",
+ "changedTouches",
+ "channel",
+ "channelCount",
+ "channelCountMode",
+ "channelInterpretation",
+ "char",
+ "charAt",
+ "charCode",
+ "charCodeAt",
+ "charIndex",
+ "charLength",
+ "characterData",
+ "characterDataOldValue",
+ "characterSet",
+ "characteristic",
+ "charging",
+ "chargingTime",
+ "charset",
+ "check",
+ "checkEnclosure",
+ "checkFramebufferStatus",
+ "checkIntersection",
+ "checkValidity",
+ "checked",
+ "childElementCount",
+ "childList",
+ "childNodes",
+ "children",
+ "chrome",
+ "ciphertext",
+ "cite",
+ "city",
+ "claimInterface",
+ "claimed",
+ "classList",
+ "className",
+ "classid",
+ "clear",
+ "clearAppBadge",
+ "clearAttributes",
+ "clearBufferfi",
+ "clearBufferfv",
+ "clearBufferiv",
+ "clearBufferuiv",
+ "clearColor",
+ "clearData",
+ "clearDepth",
+ "clearHalt",
+ "clearImmediate",
+ "clearInterval",
+ "clearLiveSeekableRange",
+ "clearMarks",
+ "clearMaxGCPauseAccumulator",
+ "clearMeasures",
+ "clearParameters",
+ "clearRect",
+ "clearResourceTimings",
+ "clearShadow",
+ "clearStencil",
+ "clearTimeout",
+ "clearWatch",
+ "click",
+ "clickCount",
+ "clientDataJSON",
+ "clientHeight",
+ "clientInformation",
+ "clientLeft",
+ "clientRect",
+ "clientRects",
+ "clientTop",
+ "clientWaitSync",
+ "clientWidth",
+ "clientX",
+ "clientY",
+ "clip",
+ "clip-path",
+ "clip-rule",
+ "clipBottom",
+ "clipLeft",
+ "clipPath",
+ "clipPathUnits",
+ "clipRight",
+ "clipRule",
+ "clipTop",
+ "clipboard",
+ "clipboardData",
+ "clone",
+ "cloneContents",
+ "cloneNode",
+ "cloneRange",
+ "close",
+ "closePath",
+ "closed",
+ "closest",
+ "clz",
+ "clz32",
+ "cm",
+ "cmp",
+ "code",
+ "codeBase",
+ "codePointAt",
+ "codeType",
+ "colSpan",
+ "collapse",
+ "collapseToEnd",
+ "collapseToStart",
+ "collapsed",
+ "collect",
+ "colno",
+ "color",
+ "color-adjust",
+ "color-interpolation",
+ "color-interpolation-filters",
+ "colorAdjust",
+ "colorDepth",
+ "colorInterpolation",
+ "colorInterpolationFilters",
+ "colorMask",
+ "colorType",
+ "cols",
+ "column-count",
+ "column-fill",
+ "column-gap",
+ "column-rule",
+ "column-rule-color",
+ "column-rule-style",
+ "column-rule-width",
+ "column-span",
+ "column-width",
+ "columnCount",
+ "columnFill",
+ "columnGap",
+ "columnNumber",
+ "columnRule",
+ "columnRuleColor",
+ "columnRuleStyle",
+ "columnRuleWidth",
+ "columnSpan",
+ "columnWidth",
+ "columns",
+ "command",
+ "commit",
+ "commitPreferences",
+ "commitStyles",
+ "commonAncestorContainer",
+ "compact",
+ "compareBoundaryPoints",
+ "compareDocumentPosition",
+ "compareEndPoints",
+ "compareExchange",
+ "compareNode",
+ "comparePoint",
+ "compatMode",
+ "compatible",
+ "compile",
+ "compileShader",
+ "compileStreaming",
+ "complete",
+ "component",
+ "componentFromPoint",
+ "composed",
+ "composedPath",
+ "composite",
+ "compositionEndOffset",
+ "compositionStartOffset",
+ "compressedTexImage2D",
+ "compressedTexImage3D",
+ "compressedTexSubImage2D",
+ "compressedTexSubImage3D",
+ "computedStyleMap",
+ "concat",
+ "conditionText",
+ "coneInnerAngle",
+ "coneOuterAngle",
+ "coneOuterGain",
+ "configuration",
+ "configurationName",
+ "configurationValue",
+ "configurations",
+ "confirm",
+ "confirmComposition",
+ "confirmSiteSpecificTrackingException",
+ "confirmWebWideTrackingException",
+ "connect",
+ "connectEnd",
+ "connectShark",
+ "connectStart",
+ "connected",
+ "connection",
+ "connectionList",
+ "connectionSpeed",
+ "connectionState",
+ "connections",
+ "console",
+ "consolidate",
+ "constraint",
+ "constrictionActive",
+ "construct",
+ "constructor",
+ "contactID",
+ "contain",
+ "containerId",
+ "containerName",
+ "containerSrc",
+ "containerType",
+ "contains",
+ "containsNode",
+ "content",
+ "contentBoxSize",
+ "contentDocument",
+ "contentEditable",
+ "contentHint",
+ "contentOverflow",
+ "contentRect",
+ "contentScriptType",
+ "contentStyleType",
+ "contentType",
+ "contentWindow",
+ "context",
+ "contextMenu",
+ "contextmenu",
+ "continue",
+ "continuePrimaryKey",
+ "continuous",
+ "control",
+ "controlTransferIn",
+ "controlTransferOut",
+ "controller",
+ "controls",
+ "controlsList",
+ "convertPointFromNode",
+ "convertQuadFromNode",
+ "convertRectFromNode",
+ "convertToBlob",
+ "convertToSpecifiedUnits",
+ "cookie",
+ "cookieEnabled",
+ "coords",
+ "copyBufferSubData",
+ "copyFromChannel",
+ "copyTexImage2D",
+ "copyTexSubImage2D",
+ "copyTexSubImage3D",
+ "copyToChannel",
+ "copyWithin",
+ "correspondingElement",
+ "correspondingUseElement",
+ "corruptedVideoFrames",
+ "cos",
+ "cosh",
+ "count",
+ "countReset",
+ "counter-increment",
+ "counter-reset",
+ "counter-set",
+ "counterIncrement",
+ "counterReset",
+ "counterSet",
+ "country",
+ "cpuClass",
+ "cpuSleepAllowed",
+ "create",
+ "createAnalyser",
+ "createAnswer",
+ "createAttribute",
+ "createAttributeNS",
+ "createBiquadFilter",
+ "createBuffer",
+ "createBufferSource",
+ "createCDATASection",
+ "createCSSStyleSheet",
+ "createCaption",
+ "createChannelMerger",
+ "createChannelSplitter",
+ "createComment",
+ "createConstantSource",
+ "createContextualFragment",
+ "createControlRange",
+ "createConvolver",
+ "createDTMFSender",
+ "createDataChannel",
+ "createDelay",
+ "createDelayNode",
+ "createDocument",
+ "createDocumentFragment",
+ "createDocumentType",
+ "createDynamicsCompressor",
+ "createElement",
+ "createElementNS",
+ "createEntityReference",
+ "createEvent",
+ "createEventObject",
+ "createExpression",
+ "createFramebuffer",
+ "createFunction",
+ "createGain",
+ "createGainNode",
+ "createHTML",
+ "createHTMLDocument",
+ "createIIRFilter",
+ "createImageBitmap",
+ "createImageData",
+ "createIndex",
+ "createJavaScriptNode",
+ "createLinearGradient",
+ "createMediaElementSource",
+ "createMediaKeys",
+ "createMediaStreamDestination",
+ "createMediaStreamSource",
+ "createMediaStreamTrackSource",
+ "createMutableFile",
+ "createNSResolver",
+ "createNodeIterator",
+ "createNotification",
+ "createObjectStore",
+ "createObjectURL",
+ "createOffer",
+ "createOscillator",
+ "createPanner",
+ "createPattern",
+ "createPeriodicWave",
+ "createPolicy",
+ "createPopup",
+ "createProcessingInstruction",
+ "createProgram",
+ "createQuery",
+ "createRadialGradient",
+ "createRange",
+ "createRangeCollection",
+ "createReader",
+ "createRenderbuffer",
+ "createSVGAngle",
+ "createSVGLength",
+ "createSVGMatrix",
+ "createSVGNumber",
+ "createSVGPathSegArcAbs",
+ "createSVGPathSegArcRel",
+ "createSVGPathSegClosePath",
+ "createSVGPathSegCurvetoCubicAbs",
+ "createSVGPathSegCurvetoCubicRel",
+ "createSVGPathSegCurvetoCubicSmoothAbs",
+ "createSVGPathSegCurvetoCubicSmoothRel",
+ "createSVGPathSegCurvetoQuadraticAbs",
+ "createSVGPathSegCurvetoQuadraticRel",
+ "createSVGPathSegCurvetoQuadraticSmoothAbs",
+ "createSVGPathSegCurvetoQuadraticSmoothRel",
+ "createSVGPathSegLinetoAbs",
+ "createSVGPathSegLinetoHorizontalAbs",
+ "createSVGPathSegLinetoHorizontalRel",
+ "createSVGPathSegLinetoRel",
+ "createSVGPathSegLinetoVerticalAbs",
+ "createSVGPathSegLinetoVerticalRel",
+ "createSVGPathSegMovetoAbs",
+ "createSVGPathSegMovetoRel",
+ "createSVGPoint",
+ "createSVGRect",
+ "createSVGTransform",
+ "createSVGTransformFromMatrix",
+ "createSampler",
+ "createScript",
+ "createScriptProcessor",
+ "createScriptURL",
+ "createSession",
+ "createShader",
+ "createShadowRoot",
+ "createStereoPanner",
+ "createStyleSheet",
+ "createTBody",
+ "createTFoot",
+ "createTHead",
+ "createTextNode",
+ "createTextRange",
+ "createTexture",
+ "createTouch",
+ "createTouchList",
+ "createTransformFeedback",
+ "createTreeWalker",
+ "createVertexArray",
+ "createWaveShaper",
+ "creationTime",
+ "credentials",
+ "crossOrigin",
+ "crossOriginIsolated",
+ "crypto",
+ "csi",
+ "csp",
+ "cssFloat",
+ "cssRules",
+ "cssText",
+ "cssValueType",
+ "ctrlKey",
+ "ctrlLeft",
+ "cues",
+ "cullFace",
+ "currentDirection",
+ "currentLocalDescription",
+ "currentNode",
+ "currentPage",
+ "currentRect",
+ "currentRemoteDescription",
+ "currentScale",
+ "currentScript",
+ "currentSrc",
+ "currentState",
+ "currentStyle",
+ "currentTarget",
+ "currentTime",
+ "currentTranslate",
+ "currentView",
+ "cursor",
+ "curve",
+ "customElements",
+ "customError",
+ "cx",
+ "cy",
+ "d",
+ "data",
+ "dataFld",
+ "dataFormatAs",
+ "dataLoss",
+ "dataLossMessage",
+ "dataPageSize",
+ "dataSrc",
+ "dataTransfer",
+ "database",
+ "databases",
+ "dataset",
+ "dateTime",
+ "db",
+ "debug",
+ "debuggerEnabled",
+ "declare",
+ "decode",
+ "decodeAudioData",
+ "decodeURI",
+ "decodeURIComponent",
+ "decodedBodySize",
+ "decoding",
+ "decodingInfo",
+ "decrypt",
+ "default",
+ "defaultCharset",
+ "defaultChecked",
+ "defaultMuted",
+ "defaultPlaybackRate",
+ "defaultPolicy",
+ "defaultPrevented",
+ "defaultRequest",
+ "defaultSelected",
+ "defaultStatus",
+ "defaultURL",
+ "defaultValue",
+ "defaultView",
+ "defaultstatus",
+ "defer",
+ "define",
+ "defineMagicFunction",
+ "defineMagicVariable",
+ "defineProperties",
+ "defineProperty",
+ "deg",
+ "delay",
+ "delayTime",
+ "delegatesFocus",
+ "delete",
+ "deleteBuffer",
+ "deleteCaption",
+ "deleteCell",
+ "deleteContents",
+ "deleteData",
+ "deleteDatabase",
+ "deleteFramebuffer",
+ "deleteFromDocument",
+ "deleteIndex",
+ "deleteMedium",
+ "deleteObjectStore",
+ "deleteProgram",
+ "deleteProperty",
+ "deleteQuery",
+ "deleteRenderbuffer",
+ "deleteRow",
+ "deleteRule",
+ "deleteSampler",
+ "deleteShader",
+ "deleteSync",
+ "deleteTFoot",
+ "deleteTHead",
+ "deleteTexture",
+ "deleteTransformFeedback",
+ "deleteVertexArray",
+ "deliverChangeRecords",
+ "delivery",
+ "deliveryInfo",
+ "deliveryStatus",
+ "deliveryTimestamp",
+ "delta",
+ "deltaMode",
+ "deltaX",
+ "deltaY",
+ "deltaZ",
+ "dependentLocality",
+ "depthFar",
+ "depthFunc",
+ "depthMask",
+ "depthNear",
+ "depthRange",
+ "deref",
+ "deriveBits",
+ "deriveKey",
+ "description",
+ "deselectAll",
+ "designMode",
+ "desiredSize",
+ "destination",
+ "destinationURL",
+ "detach",
+ "detachEvent",
+ "detachShader",
+ "detail",
+ "details",
+ "detect",
+ "detune",
+ "device",
+ "deviceClass",
+ "deviceId",
+ "deviceMemory",
+ "devicePixelContentBoxSize",
+ "devicePixelRatio",
+ "deviceProtocol",
+ "deviceSubclass",
+ "deviceVersionMajor",
+ "deviceVersionMinor",
+ "deviceVersionSubminor",
+ "deviceXDPI",
+ "deviceYDPI",
+ "didTimeout",
+ "diffuseConstant",
+ "digest",
+ "dimensions",
+ "dir",
+ "dirName",
+ "direction",
+ "dirxml",
+ "disable",
+ "disablePictureInPicture",
+ "disableRemotePlayback",
+ "disableVertexAttribArray",
+ "disabled",
+ "dischargingTime",
+ "disconnect",
+ "disconnectShark",
+ "dispatchEvent",
+ "display",
+ "displayId",
+ "displayName",
+ "disposition",
+ "distanceModel",
+ "div",
+ "divisor",
+ "djsapi",
+ "djsproxy",
+ "doImport",
+ "doNotTrack",
+ "doScroll",
+ "doctype",
+ "document",
+ "documentElement",
+ "documentMode",
+ "documentURI",
+ "dolphin",
+ "dolphinGameCenter",
+ "dolphininfo",
+ "dolphinmeta",
+ "domComplete",
+ "domContentLoadedEventEnd",
+ "domContentLoadedEventStart",
+ "domInteractive",
+ "domLoading",
+ "domOverlayState",
+ "domain",
+ "domainLookupEnd",
+ "domainLookupStart",
+ "dominant-baseline",
+ "dominantBaseline",
+ "done",
+ "dopplerFactor",
+ "dotAll",
+ "downDegrees",
+ "downlink",
+ "download",
+ "downloadTotal",
+ "downloaded",
+ "dpcm",
+ "dpi",
+ "dppx",
+ "dragDrop",
+ "draggable",
+ "drawArrays",
+ "drawArraysInstanced",
+ "drawArraysInstancedANGLE",
+ "drawBuffers",
+ "drawCustomFocusRing",
+ "drawElements",
+ "drawElementsInstanced",
+ "drawElementsInstancedANGLE",
+ "drawFocusIfNeeded",
+ "drawImage",
+ "drawImageFromRect",
+ "drawRangeElements",
+ "drawSystemFocusRing",
+ "drawingBufferHeight",
+ "drawingBufferWidth",
+ "dropEffect",
+ "droppedVideoFrames",
+ "dropzone",
+ "dtmf",
+ "dump",
+ "dumpProfile",
+ "duplicate",
+ "durability",
+ "duration",
+ "dvname",
+ "dvnum",
+ "dx",
+ "dy",
+ "dynsrc",
+ "e",
+ "edgeMode",
+ "effect",
+ "effectAllowed",
+ "effectiveDirective",
+ "effectiveType",
+ "elapsedTime",
+ "element",
+ "elementFromPoint",
+ "elementTiming",
+ "elements",
+ "elementsFromPoint",
+ "elevation",
+ "ellipse",
+ "em",
+ "email",
+ "embeds",
+ "emma",
+ "empty",
+ "empty-cells",
+ "emptyCells",
+ "emptyHTML",
+ "emptyScript",
+ "emulatedPosition",
+ "enable",
+ "enableBackground",
+ "enableDelegations",
+ "enableStyleSheetsForSet",
+ "enableVertexAttribArray",
+ "enabled",
+ "enabledPlugin",
+ "encode",
+ "encodeInto",
+ "encodeURI",
+ "encodeURIComponent",
+ "encodedBodySize",
+ "encoding",
+ "encodingInfo",
+ "encrypt",
+ "enctype",
+ "end",
+ "endContainer",
+ "endElement",
+ "endElementAt",
+ "endOfStream",
+ "endOffset",
+ "endQuery",
+ "endTime",
+ "endTransformFeedback",
+ "ended",
+ "endpoint",
+ "endpointNumber",
+ "endpoints",
+ "endsWith",
+ "enterKeyHint",
+ "entities",
+ "entries",
+ "entryType",
+ "enumerate",
+ "enumerateDevices",
+ "enumerateEditable",
+ "environmentBlendMode",
+ "equals",
+ "error",
+ "errorCode",
+ "errorDetail",
+ "errorText",
+ "escape",
+ "estimate",
+ "eval",
+ "evaluate",
+ "event",
+ "eventPhase",
+ "every",
+ "ex",
+ "exception",
+ "exchange",
+ "exec",
+ "execCommand",
+ "execCommandShowHelp",
+ "execScript",
+ "exitFullscreen",
+ "exitPictureInPicture",
+ "exitPointerLock",
+ "exitPresent",
+ "exp",
+ "expand",
+ "expandEntityReferences",
+ "expando",
+ "expansion",
+ "expiration",
+ "expirationTime",
+ "expires",
+ "expiryDate",
+ "explicitOriginalTarget",
+ "expm1",
+ "exponent",
+ "exponentialRampToValueAtTime",
+ "exportKey",
+ "extend",
+ "extensions",
+ "extentNode",
+ "extentOffset",
+ "external",
+ "externalResourcesRequired",
+ "extractContents",
+ "extractable",
+ "eye",
+ "f",
+ "face",
+ "factoryReset",
+ "failureReason",
+ "fallback",
+ "family",
+ "familyName",
+ "farthestViewportElement",
+ "fastSeek",
+ "fatal",
+ "featureId",
+ "featurePolicy",
+ "featureSettings",
+ "features",
+ "fenceSync",
+ "fetch",
+ "fetchStart",
+ "fftSize",
+ "fgColor",
+ "fieldOfView",
+ "file",
+ "fileCreatedDate",
+ "fileHandle",
+ "fileModifiedDate",
+ "fileName",
+ "fileSize",
+ "fileUpdatedDate",
+ "filename",
+ "files",
+ "filesystem",
+ "fill",
+ "fill-opacity",
+ "fill-rule",
+ "fillLightMode",
+ "fillOpacity",
+ "fillRect",
+ "fillRule",
+ "fillStyle",
+ "fillText",
+ "filter",
+ "filterResX",
+ "filterResY",
+ "filterUnits",
+ "filters",
+ "finally",
+ "find",
+ "findIndex",
+ "findRule",
+ "findText",
+ "finish",
+ "finished",
+ "fireEvent",
+ "firesTouchEvents",
+ "firstChild",
+ "firstElementChild",
+ "firstPage",
+ "fixed",
+ "flags",
+ "flat",
+ "flatMap",
+ "flex",
+ "flex-basis",
+ "flex-direction",
+ "flex-flow",
+ "flex-grow",
+ "flex-shrink",
+ "flex-wrap",
+ "flexBasis",
+ "flexDirection",
+ "flexFlow",
+ "flexGrow",
+ "flexShrink",
+ "flexWrap",
+ "flipX",
+ "flipY",
+ "float",
+ "float32",
+ "float64",
+ "flood-color",
+ "flood-opacity",
+ "floodColor",
+ "floodOpacity",
+ "floor",
+ "flush",
+ "focus",
+ "focusNode",
+ "focusOffset",
+ "font",
+ "font-family",
+ "font-feature-settings",
+ "font-kerning",
+ "font-language-override",
+ "font-optical-sizing",
+ "font-size",
+ "font-size-adjust",
+ "font-stretch",
+ "font-style",
+ "font-synthesis",
+ "font-variant",
+ "font-variant-alternates",
+ "font-variant-caps",
+ "font-variant-east-asian",
+ "font-variant-ligatures",
+ "font-variant-numeric",
+ "font-variant-position",
+ "font-variation-settings",
+ "font-weight",
+ "fontFamily",
+ "fontFeatureSettings",
+ "fontKerning",
+ "fontLanguageOverride",
+ "fontOpticalSizing",
+ "fontSize",
+ "fontSizeAdjust",
+ "fontSmoothingEnabled",
+ "fontStretch",
+ "fontStyle",
+ "fontSynthesis",
+ "fontVariant",
+ "fontVariantAlternates",
+ "fontVariantCaps",
+ "fontVariantEastAsian",
+ "fontVariantLigatures",
+ "fontVariantNumeric",
+ "fontVariantPosition",
+ "fontVariationSettings",
+ "fontWeight",
+ "fontcolor",
+ "fontfaces",
+ "fonts",
+ "fontsize",
+ "for",
+ "forEach",
+ "force",
+ "forceRedraw",
+ "form",
+ "formAction",
+ "formData",
+ "formEnctype",
+ "formMethod",
+ "formNoValidate",
+ "formTarget",
+ "format",
+ "formatToParts",
+ "forms",
+ "forward",
+ "forwardX",
+ "forwardY",
+ "forwardZ",
+ "foundation",
+ "fr",
+ "fragmentDirective",
+ "frame",
+ "frameBorder",
+ "frameElement",
+ "frameSpacing",
+ "framebuffer",
+ "framebufferHeight",
+ "framebufferRenderbuffer",
+ "framebufferTexture2D",
+ "framebufferTextureLayer",
+ "framebufferWidth",
+ "frames",
+ "freeSpace",
+ "freeze",
+ "frequency",
+ "frequencyBinCount",
+ "from",
+ "fromCharCode",
+ "fromCodePoint",
+ "fromElement",
+ "fromEntries",
+ "fromFloat32Array",
+ "fromFloat64Array",
+ "fromMatrix",
+ "fromPoint",
+ "fromQuad",
+ "fromRect",
+ "frontFace",
+ "fround",
+ "fullPath",
+ "fullScreen",
+ "fullscreen",
+ "fullscreenElement",
+ "fullscreenEnabled",
+ "fx",
+ "fy",
+ "gain",
+ "gamepad",
+ "gamma",
+ "gap",
+ "gatheringState",
+ "gatt",
+ "genderIdentity",
+ "generateCertificate",
+ "generateKey",
+ "generateMipmap",
+ "generateRequest",
+ "geolocation",
+ "gestureObject",
+ "get",
+ "getActiveAttrib",
+ "getActiveUniform",
+ "getActiveUniformBlockName",
+ "getActiveUniformBlockParameter",
+ "getActiveUniforms",
+ "getAdjacentText",
+ "getAll",
+ "getAllKeys",
+ "getAllResponseHeaders",
+ "getAllowlistForFeature",
+ "getAnimations",
+ "getAsFile",
+ "getAsString",
+ "getAttachedShaders",
+ "getAttribLocation",
+ "getAttribute",
+ "getAttributeNS",
+ "getAttributeNames",
+ "getAttributeNode",
+ "getAttributeNodeNS",
+ "getAttributeType",
+ "getAudioTracks",
+ "getAvailability",
+ "getBBox",
+ "getBattery",
+ "getBigInt64",
+ "getBigUint64",
+ "getBlob",
+ "getBookmark",
+ "getBoundingClientRect",
+ "getBounds",
+ "getBoxQuads",
+ "getBufferParameter",
+ "getBufferSubData",
+ "getByteFrequencyData",
+ "getByteTimeDomainData",
+ "getCSSCanvasContext",
+ "getCTM",
+ "getCandidateWindowClientRect",
+ "getCanonicalLocales",
+ "getCapabilities",
+ "getChannelData",
+ "getCharNumAtPosition",
+ "getCharacteristic",
+ "getCharacteristics",
+ "getClientExtensionResults",
+ "getClientRect",
+ "getClientRects",
+ "getCoalescedEvents",
+ "getCompositionAlternatives",
+ "getComputedStyle",
+ "getComputedTextLength",
+ "getComputedTiming",
+ "getConfiguration",
+ "getConstraints",
+ "getContext",
+ "getContextAttributes",
+ "getContributingSources",
+ "getCounterValue",
+ "getCueAsHTML",
+ "getCueById",
+ "getCurrentPosition",
+ "getCurrentTime",
+ "getData",
+ "getDatabaseNames",
+ "getDate",
+ "getDay",
+ "getDefaultComputedStyle",
+ "getDescriptor",
+ "getDescriptors",
+ "getDestinationInsertionPoints",
+ "getDevices",
+ "getDirectory",
+ "getDisplayMedia",
+ "getDistributedNodes",
+ "getEditable",
+ "getElementById",
+ "getElementsByClassName",
+ "getElementsByName",
+ "getElementsByTagName",
+ "getElementsByTagNameNS",
+ "getEnclosureList",
+ "getEndPositionOfChar",
+ "getEntries",
+ "getEntriesByName",
+ "getEntriesByType",
+ "getError",
+ "getExtension",
+ "getExtentOfChar",
+ "getEyeParameters",
+ "getFeature",
+ "getFile",
+ "getFiles",
+ "getFilesAndDirectories",
+ "getFingerprints",
+ "getFloat32",
+ "getFloat64",
+ "getFloatFrequencyData",
+ "getFloatTimeDomainData",
+ "getFloatValue",
+ "getFragDataLocation",
+ "getFrameData",
+ "getFramebufferAttachmentParameter",
+ "getFrequencyResponse",
+ "getFullYear",
+ "getGamepads",
+ "getHitTestResults",
+ "getHitTestResultsForTransientInput",
+ "getHours",
+ "getIdentityAssertion",
+ "getIds",
+ "getImageData",
+ "getIndexedParameter",
+ "getInstalledRelatedApps",
+ "getInt16",
+ "getInt32",
+ "getInt8",
+ "getInternalformatParameter",
+ "getIntersectionList",
+ "getItem",
+ "getItems",
+ "getKey",
+ "getKeyframes",
+ "getLayers",
+ "getLayoutMap",
+ "getLineDash",
+ "getLocalCandidates",
+ "getLocalParameters",
+ "getLocalStreams",
+ "getMarks",
+ "getMatchedCSSRules",
+ "getMaxGCPauseSinceClear",
+ "getMeasures",
+ "getMetadata",
+ "getMilliseconds",
+ "getMinutes",
+ "getModifierState",
+ "getMonth",
+ "getNamedItem",
+ "getNamedItemNS",
+ "getNativeFramebufferScaleFactor",
+ "getNotifications",
+ "getNotifier",
+ "getNumberOfChars",
+ "getOffsetReferenceSpace",
+ "getOutputTimestamp",
+ "getOverrideHistoryNavigationMode",
+ "getOverrideStyle",
+ "getOwnPropertyDescriptor",
+ "getOwnPropertyDescriptors",
+ "getOwnPropertyNames",
+ "getOwnPropertySymbols",
+ "getParameter",
+ "getParameters",
+ "getParent",
+ "getPathSegAtLength",
+ "getPhotoCapabilities",
+ "getPhotoSettings",
+ "getPointAtLength",
+ "getPose",
+ "getPredictedEvents",
+ "getPreference",
+ "getPreferenceDefault",
+ "getPresentationAttribute",
+ "getPreventDefault",
+ "getPrimaryService",
+ "getPrimaryServices",
+ "getProgramInfoLog",
+ "getProgramParameter",
+ "getPropertyCSSValue",
+ "getPropertyPriority",
+ "getPropertyShorthand",
+ "getPropertyType",
+ "getPropertyValue",
+ "getPrototypeOf",
+ "getQuery",
+ "getQueryParameter",
+ "getRGBColorValue",
+ "getRandomValues",
+ "getRangeAt",
+ "getReader",
+ "getReceivers",
+ "getRectValue",
+ "getRegistration",
+ "getRegistrations",
+ "getRemoteCandidates",
+ "getRemoteCertificates",
+ "getRemoteParameters",
+ "getRemoteStreams",
+ "getRenderbufferParameter",
+ "getResponseHeader",
+ "getRoot",
+ "getRootNode",
+ "getRotationOfChar",
+ "getSVGDocument",
+ "getSamplerParameter",
+ "getScreenCTM",
+ "getSeconds",
+ "getSelectedCandidatePair",
+ "getSelection",
+ "getSenders",
+ "getService",
+ "getSettings",
+ "getShaderInfoLog",
+ "getShaderParameter",
+ "getShaderPrecisionFormat",
+ "getShaderSource",
+ "getSimpleDuration",
+ "getSiteIcons",
+ "getSources",
+ "getSpeculativeParserUrls",
+ "getStartPositionOfChar",
+ "getStartTime",
+ "getState",
+ "getStats",
+ "getStatusForPolicy",
+ "getStorageUpdates",
+ "getStreamById",
+ "getStringValue",
+ "getSubStringLength",
+ "getSubscription",
+ "getSupportedConstraints",
+ "getSupportedExtensions",
+ "getSupportedFormats",
+ "getSyncParameter",
+ "getSynchronizationSources",
+ "getTags",
+ "getTargetRanges",
+ "getTexParameter",
+ "getTime",
+ "getTimezoneOffset",
+ "getTiming",
+ "getTotalLength",
+ "getTrackById",
+ "getTracks",
+ "getTransceivers",
+ "getTransform",
+ "getTransformFeedbackVarying",
+ "getTransformToElement",
+ "getTransports",
+ "getType",
+ "getTypeMapping",
+ "getUTCDate",
+ "getUTCDay",
+ "getUTCFullYear",
+ "getUTCHours",
+ "getUTCMilliseconds",
+ "getUTCMinutes",
+ "getUTCMonth",
+ "getUTCSeconds",
+ "getUint16",
+ "getUint32",
+ "getUint8",
+ "getUniform",
+ "getUniformBlockIndex",
+ "getUniformIndices",
+ "getUniformLocation",
+ "getUserMedia",
+ "getVRDisplays",
+ "getValues",
+ "getVarDate",
+ "getVariableValue",
+ "getVertexAttrib",
+ "getVertexAttribOffset",
+ "getVideoPlaybackQuality",
+ "getVideoTracks",
+ "getViewerPose",
+ "getViewport",
+ "getVoices",
+ "getWakeLockState",
+ "getWriter",
+ "getYear",
+ "givenName",
+ "global",
+ "globalAlpha",
+ "globalCompositeOperation",
+ "globalThis",
+ "glyphOrientationHorizontal",
+ "glyphOrientationVertical",
+ "glyphRef",
+ "go",
+ "grabFrame",
+ "grad",
+ "gradientTransform",
+ "gradientUnits",
+ "grammars",
+ "green",
+ "grid",
+ "grid-area",
+ "grid-auto-columns",
+ "grid-auto-flow",
+ "grid-auto-rows",
+ "grid-column",
+ "grid-column-end",
+ "grid-column-gap",
+ "grid-column-start",
+ "grid-gap",
+ "grid-row",
+ "grid-row-end",
+ "grid-row-gap",
+ "grid-row-start",
+ "grid-template",
+ "grid-template-areas",
+ "grid-template-columns",
+ "grid-template-rows",
+ "gridArea",
+ "gridAutoColumns",
+ "gridAutoFlow",
+ "gridAutoRows",
+ "gridColumn",
+ "gridColumnEnd",
+ "gridColumnGap",
+ "gridColumnStart",
+ "gridGap",
+ "gridRow",
+ "gridRowEnd",
+ "gridRowGap",
+ "gridRowStart",
+ "gridTemplate",
+ "gridTemplateAreas",
+ "gridTemplateColumns",
+ "gridTemplateRows",
+ "gripSpace",
+ "group",
+ "groupCollapsed",
+ "groupEnd",
+ "groupId",
+ "hadRecentInput",
+ "hand",
+ "handedness",
+ "hapticActuators",
+ "hardwareConcurrency",
+ "has",
+ "hasAttribute",
+ "hasAttributeNS",
+ "hasAttributes",
+ "hasBeenActive",
+ "hasChildNodes",
+ "hasComposition",
+ "hasEnrolledInstrument",
+ "hasExtension",
+ "hasExternalDisplay",
+ "hasFeature",
+ "hasFocus",
+ "hasInstance",
+ "hasLayout",
+ "hasOrientation",
+ "hasOwnProperty",
+ "hasPointerCapture",
+ "hasPosition",
+ "hasReading",
+ "hasStorageAccess",
+ "hash",
+ "head",
+ "headers",
+ "heading",
+ "height",
+ "hidden",
+ "hide",
+ "hideFocus",
+ "high",
+ "highWaterMark",
+ "hint",
+ "history",
+ "honorificPrefix",
+ "honorificSuffix",
+ "horizontalOverflow",
+ "host",
+ "hostCandidate",
+ "hostname",
+ "href",
+ "hrefTranslate",
+ "hreflang",
+ "hspace",
+ "html5TagCheckInerface",
+ "htmlFor",
+ "htmlText",
+ "httpEquiv",
+ "httpRequestStatusCode",
+ "hwTimestamp",
+ "hyphens",
+ "hypot",
+ "iccId",
+ "iceConnectionState",
+ "iceGatheringState",
+ "iceTransport",
+ "icon",
+ "iconURL",
+ "id",
+ "identifier",
+ "identity",
+ "idpLoginUrl",
+ "ignoreBOM",
+ "ignoreCase",
+ "ignoreDepthValues",
+ "image-orientation",
+ "image-rendering",
+ "imageHeight",
+ "imageOrientation",
+ "imageRendering",
+ "imageSizes",
+ "imageSmoothingEnabled",
+ "imageSmoothingQuality",
+ "imageSrcset",
+ "imageWidth",
+ "images",
+ "ime-mode",
+ "imeMode",
+ "implementation",
+ "importKey",
+ "importNode",
+ "importStylesheet",
+ "imports",
+ "impp",
+ "imul",
+ "in",
+ "in1",
+ "in2",
+ "inBandMetadataTrackDispatchType",
+ "inRange",
+ "includes",
+ "incremental",
+ "indeterminate",
+ "index",
+ "indexNames",
+ "indexOf",
+ "indexedDB",
+ "indicate",
+ "inertiaDestinationX",
+ "inertiaDestinationY",
+ "info",
+ "init",
+ "initAnimationEvent",
+ "initBeforeLoadEvent",
+ "initClipboardEvent",
+ "initCloseEvent",
+ "initCommandEvent",
+ "initCompositionEvent",
+ "initCustomEvent",
+ "initData",
+ "initDataType",
+ "initDeviceMotionEvent",
+ "initDeviceOrientationEvent",
+ "initDragEvent",
+ "initErrorEvent",
+ "initEvent",
+ "initFocusEvent",
+ "initGestureEvent",
+ "initHashChangeEvent",
+ "initKeyEvent",
+ "initKeyboardEvent",
+ "initMSManipulationEvent",
+ "initMessageEvent",
+ "initMouseEvent",
+ "initMouseScrollEvent",
+ "initMouseWheelEvent",
+ "initMutationEvent",
+ "initNSMouseEvent",
+ "initOverflowEvent",
+ "initPageEvent",
+ "initPageTransitionEvent",
+ "initPointerEvent",
+ "initPopStateEvent",
+ "initProgressEvent",
+ "initScrollAreaEvent",
+ "initSimpleGestureEvent",
+ "initStorageEvent",
+ "initTextEvent",
+ "initTimeEvent",
+ "initTouchEvent",
+ "initTransitionEvent",
+ "initUIEvent",
+ "initWebKitAnimationEvent",
+ "initWebKitTransitionEvent",
+ "initWebKitWheelEvent",
+ "initWheelEvent",
+ "initialTime",
+ "initialize",
+ "initiatorType",
+ "inline-size",
+ "inlineSize",
+ "inlineVerticalFieldOfView",
+ "inner",
+ "innerHTML",
+ "innerHeight",
+ "innerText",
+ "innerWidth",
+ "input",
+ "inputBuffer",
+ "inputEncoding",
+ "inputMethod",
+ "inputMode",
+ "inputSource",
+ "inputSources",
+ "inputType",
+ "inputs",
+ "insertAdjacentElement",
+ "insertAdjacentHTML",
+ "insertAdjacentText",
+ "insertBefore",
+ "insertCell",
+ "insertDTMF",
+ "insertData",
+ "insertItemBefore",
+ "insertNode",
+ "insertRow",
+ "insertRule",
+ "inset",
+ "inset-block",
+ "inset-block-end",
+ "inset-block-start",
+ "inset-inline",
+ "inset-inline-end",
+ "inset-inline-start",
+ "insetBlock",
+ "insetBlockEnd",
+ "insetBlockStart",
+ "insetInline",
+ "insetInlineEnd",
+ "insetInlineStart",
+ "installing",
+ "instanceRoot",
+ "instantiate",
+ "instantiateStreaming",
+ "instruments",
+ "int16",
+ "int32",
+ "int8",
+ "integrity",
+ "interactionMode",
+ "intercept",
+ "interfaceClass",
+ "interfaceName",
+ "interfaceNumber",
+ "interfaceProtocol",
+ "interfaceSubclass",
+ "interfaces",
+ "interimResults",
+ "internalSubset",
+ "interpretation",
+ "intersectionRatio",
+ "intersectionRect",
+ "intersectsNode",
+ "interval",
+ "invalidIteratorState",
+ "invalidateFramebuffer",
+ "invalidateSubFramebuffer",
+ "inverse",
+ "invertSelf",
+ "is",
+ "is2D",
+ "isActive",
+ "isAlternate",
+ "isArray",
+ "isBingCurrentSearchDefault",
+ "isBuffer",
+ "isCandidateWindowVisible",
+ "isChar",
+ "isCollapsed",
+ "isComposing",
+ "isConcatSpreadable",
+ "isConnected",
+ "isContentEditable",
+ "isContentHandlerRegistered",
+ "isContextLost",
+ "isDefaultNamespace",
+ "isDirectory",
+ "isDisabled",
+ "isEnabled",
+ "isEqual",
+ "isEqualNode",
+ "isExtensible",
+ "isExternalCTAP2SecurityKeySupported",
+ "isFile",
+ "isFinite",
+ "isFramebuffer",
+ "isFrozen",
+ "isGenerator",
+ "isHTML",
+ "isHistoryNavigation",
+ "isId",
+ "isIdentity",
+ "isInjected",
+ "isInteger",
+ "isIntersecting",
+ "isLockFree",
+ "isMap",
+ "isMultiLine",
+ "isNaN",
+ "isOpen",
+ "isPointInFill",
+ "isPointInPath",
+ "isPointInRange",
+ "isPointInStroke",
+ "isPrefAlternate",
+ "isPresenting",
+ "isPrimary",
+ "isProgram",
+ "isPropertyImplicit",
+ "isProtocolHandlerRegistered",
+ "isPrototypeOf",
+ "isQuery",
+ "isRenderbuffer",
+ "isSafeInteger",
+ "isSameNode",
+ "isSampler",
+ "isScript",
+ "isScriptURL",
+ "isSealed",
+ "isSecureContext",
+ "isSessionSupported",
+ "isShader",
+ "isSupported",
+ "isSync",
+ "isTextEdit",
+ "isTexture",
+ "isTransformFeedback",
+ "isTrusted",
+ "isTypeSupported",
+ "isUserVerifyingPlatformAuthenticatorAvailable",
+ "isVertexArray",
+ "isView",
+ "isVisible",
+ "isochronousTransferIn",
+ "isochronousTransferOut",
+ "isolation",
+ "italics",
+ "item",
+ "itemId",
+ "itemProp",
+ "itemRef",
+ "itemScope",
+ "itemType",
+ "itemValue",
+ "items",
+ "iterateNext",
+ "iterationComposite",
+ "iterator",
+ "javaEnabled",
+ "jobTitle",
+ "join",
+ "json",
+ "justify-content",
+ "justify-items",
+ "justify-self",
+ "justifyContent",
+ "justifyItems",
+ "justifySelf",
+ "k1",
+ "k2",
+ "k3",
+ "k4",
+ "kHz",
+ "keepalive",
+ "kernelMatrix",
+ "kernelUnitLengthX",
+ "kernelUnitLengthY",
+ "kerning",
+ "key",
+ "keyCode",
+ "keyFor",
+ "keyIdentifier",
+ "keyLightEnabled",
+ "keyLocation",
+ "keyPath",
+ "keyStatuses",
+ "keySystem",
+ "keyText",
+ "keyUsage",
+ "keyboard",
+ "keys",
+ "keytype",
+ "kind",
+ "knee",
+ "label",
+ "labels",
+ "lang",
+ "language",
+ "languages",
+ "largeArcFlag",
+ "lastChild",
+ "lastElementChild",
+ "lastEventId",
+ "lastIndex",
+ "lastIndexOf",
+ "lastInputTime",
+ "lastMatch",
+ "lastMessageSubject",
+ "lastMessageType",
+ "lastModified",
+ "lastModifiedDate",
+ "lastPage",
+ "lastParen",
+ "lastState",
+ "lastStyleSheetSet",
+ "latitude",
+ "layerX",
+ "layerY",
+ "layoutFlow",
+ "layoutGrid",
+ "layoutGridChar",
+ "layoutGridLine",
+ "layoutGridMode",
+ "layoutGridType",
+ "lbound",
+ "left",
+ "leftContext",
+ "leftDegrees",
+ "leftMargin",
+ "leftProjectionMatrix",
+ "leftViewMatrix",
+ "length",
+ "lengthAdjust",
+ "lengthComputable",
+ "letter-spacing",
+ "letterSpacing",
+ "level",
+ "lighting-color",
+ "lightingColor",
+ "limitingConeAngle",
+ "line",
+ "line-break",
+ "line-height",
+ "lineAlign",
+ "lineBreak",
+ "lineCap",
+ "lineDashOffset",
+ "lineHeight",
+ "lineJoin",
+ "lineNumber",
+ "lineTo",
+ "lineWidth",
+ "linearAcceleration",
+ "linearRampToValueAtTime",
+ "linearVelocity",
+ "lineno",
+ "lines",
+ "link",
+ "linkColor",
+ "linkProgram",
+ "links",
+ "list",
+ "list-style",
+ "list-style-image",
+ "list-style-position",
+ "list-style-type",
+ "listStyle",
+ "listStyleImage",
+ "listStylePosition",
+ "listStyleType",
+ "listener",
+ "load",
+ "loadEventEnd",
+ "loadEventStart",
+ "loadTime",
+ "loadTimes",
+ "loaded",
+ "loading",
+ "localDescription",
+ "localName",
+ "localService",
+ "localStorage",
+ "locale",
+ "localeCompare",
+ "location",
+ "locationbar",
+ "lock",
+ "locked",
+ "lockedFile",
+ "locks",
+ "log",
+ "log10",
+ "log1p",
+ "log2",
+ "logicalXDPI",
+ "logicalYDPI",
+ "longDesc",
+ "longitude",
+ "lookupNamespaceURI",
+ "lookupPrefix",
+ "loop",
+ "loopEnd",
+ "loopStart",
+ "looping",
+ "low",
+ "lower",
+ "lowerBound",
+ "lowerOpen",
+ "lowsrc",
+ "m11",
+ "m12",
+ "m13",
+ "m14",
+ "m21",
+ "m22",
+ "m23",
+ "m24",
+ "m31",
+ "m32",
+ "m33",
+ "m34",
+ "m41",
+ "m42",
+ "m43",
+ "m44",
+ "makeXRCompatible",
+ "manifest",
+ "manufacturer",
+ "manufacturerName",
+ "map",
+ "mapping",
+ "margin",
+ "margin-block",
+ "margin-block-end",
+ "margin-block-start",
+ "margin-bottom",
+ "margin-inline",
+ "margin-inline-end",
+ "margin-inline-start",
+ "margin-left",
+ "margin-right",
+ "margin-top",
+ "marginBlock",
+ "marginBlockEnd",
+ "marginBlockStart",
+ "marginBottom",
+ "marginHeight",
+ "marginInline",
+ "marginInlineEnd",
+ "marginInlineStart",
+ "marginLeft",
+ "marginRight",
+ "marginTop",
+ "marginWidth",
+ "mark",
+ "marker",
+ "marker-end",
+ "marker-mid",
+ "marker-offset",
+ "marker-start",
+ "markerEnd",
+ "markerHeight",
+ "markerMid",
+ "markerOffset",
+ "markerStart",
+ "markerUnits",
+ "markerWidth",
+ "marks",
+ "mask",
+ "mask-clip",
+ "mask-composite",
+ "mask-image",
+ "mask-mode",
+ "mask-origin",
+ "mask-position",
+ "mask-position-x",
+ "mask-position-y",
+ "mask-repeat",
+ "mask-size",
+ "mask-type",
+ "maskClip",
+ "maskComposite",
+ "maskContentUnits",
+ "maskImage",
+ "maskMode",
+ "maskOrigin",
+ "maskPosition",
+ "maskPositionX",
+ "maskPositionY",
+ "maskRepeat",
+ "maskSize",
+ "maskType",
+ "maskUnits",
+ "match",
+ "matchAll",
+ "matchMedia",
+ "matchMedium",
+ "matches",
+ "matrix",
+ "matrixTransform",
+ "max",
+ "max-block-size",
+ "max-height",
+ "max-inline-size",
+ "max-width",
+ "maxActions",
+ "maxAlternatives",
+ "maxBlockSize",
+ "maxChannelCount",
+ "maxChannels",
+ "maxConnectionsPerServer",
+ "maxDecibels",
+ "maxDistance",
+ "maxHeight",
+ "maxInlineSize",
+ "maxLayers",
+ "maxLength",
+ "maxMessageSize",
+ "maxPacketLifeTime",
+ "maxRetransmits",
+ "maxTouchPoints",
+ "maxValue",
+ "maxWidth",
+ "measure",
+ "measureText",
+ "media",
+ "mediaCapabilities",
+ "mediaDevices",
+ "mediaElement",
+ "mediaGroup",
+ "mediaKeys",
+ "mediaSession",
+ "mediaStream",
+ "mediaText",
+ "meetOrSlice",
+ "memory",
+ "menubar",
+ "mergeAttributes",
+ "message",
+ "messageClass",
+ "messageHandlers",
+ "messageType",
+ "metaKey",
+ "metadata",
+ "method",
+ "methodDetails",
+ "methodName",
+ "mid",
+ "mimeType",
+ "mimeTypes",
+ "min",
+ "min-block-size",
+ "min-height",
+ "min-inline-size",
+ "min-width",
+ "minBlockSize",
+ "minDecibels",
+ "minHeight",
+ "minInlineSize",
+ "minLength",
+ "minValue",
+ "minWidth",
+ "miterLimit",
+ "mix-blend-mode",
+ "mixBlendMode",
+ "mm",
+ "mode",
+ "modify",
+ "mount",
+ "move",
+ "moveBy",
+ "moveEnd",
+ "moveFirst",
+ "moveFocusDown",
+ "moveFocusLeft",
+ "moveFocusRight",
+ "moveFocusUp",
+ "moveNext",
+ "moveRow",
+ "moveStart",
+ "moveTo",
+ "moveToBookmark",
+ "moveToElementText",
+ "moveToPoint",
+ "movementX",
+ "movementY",
+ "mozAdd",
+ "mozAnimationStartTime",
+ "mozAnon",
+ "mozApps",
+ "mozAudioCaptured",
+ "mozAudioChannelType",
+ "mozAutoplayEnabled",
+ "mozCancelAnimationFrame",
+ "mozCancelFullScreen",
+ "mozCancelRequestAnimationFrame",
+ "mozCaptureStream",
+ "mozCaptureStreamUntilEnded",
+ "mozClearDataAt",
+ "mozContact",
+ "mozContacts",
+ "mozCreateFileHandle",
+ "mozCurrentTransform",
+ "mozCurrentTransformInverse",
+ "mozCursor",
+ "mozDash",
+ "mozDashOffset",
+ "mozDecodedFrames",
+ "mozExitPointerLock",
+ "mozFillRule",
+ "mozFragmentEnd",
+ "mozFrameDelay",
+ "mozFullScreen",
+ "mozFullScreenElement",
+ "mozFullScreenEnabled",
+ "mozGetAll",
+ "mozGetAllKeys",
+ "mozGetAsFile",
+ "mozGetDataAt",
+ "mozGetMetadata",
+ "mozGetUserMedia",
+ "mozHasAudio",
+ "mozHasItem",
+ "mozHidden",
+ "mozImageSmoothingEnabled",
+ "mozIndexedDB",
+ "mozInnerScreenX",
+ "mozInnerScreenY",
+ "mozInputSource",
+ "mozIsTextField",
+ "mozItem",
+ "mozItemCount",
+ "mozItems",
+ "mozLength",
+ "mozLockOrientation",
+ "mozMatchesSelector",
+ "mozMovementX",
+ "mozMovementY",
+ "mozOpaque",
+ "mozOrientation",
+ "mozPaintCount",
+ "mozPaintedFrames",
+ "mozParsedFrames",
+ "mozPay",
+ "mozPointerLockElement",
+ "mozPresentedFrames",
+ "mozPreservesPitch",
+ "mozPressure",
+ "mozPrintCallback",
+ "mozRTCIceCandidate",
+ "mozRTCPeerConnection",
+ "mozRTCSessionDescription",
+ "mozRemove",
+ "mozRequestAnimationFrame",
+ "mozRequestFullScreen",
+ "mozRequestPointerLock",
+ "mozSetDataAt",
+ "mozSetImageElement",
+ "mozSourceNode",
+ "mozSrcObject",
+ "mozSystem",
+ "mozTCPSocket",
+ "mozTextStyle",
+ "mozTypesAt",
+ "mozUnlockOrientation",
+ "mozUserCancelled",
+ "mozVisibilityState",
+ "ms",
+ "msAnimation",
+ "msAnimationDelay",
+ "msAnimationDirection",
+ "msAnimationDuration",
+ "msAnimationFillMode",
+ "msAnimationIterationCount",
+ "msAnimationName",
+ "msAnimationPlayState",
+ "msAnimationStartTime",
+ "msAnimationTimingFunction",
+ "msBackfaceVisibility",
+ "msBlockProgression",
+ "msCSSOMElementFloatMetrics",
+ "msCaching",
+ "msCachingEnabled",
+ "msCancelRequestAnimationFrame",
+ "msCapsLockWarningOff",
+ "msClearImmediate",
+ "msClose",
+ "msContentZoomChaining",
+ "msContentZoomFactor",
+ "msContentZoomLimit",
+ "msContentZoomLimitMax",
+ "msContentZoomLimitMin",
+ "msContentZoomSnap",
+ "msContentZoomSnapPoints",
+ "msContentZoomSnapType",
+ "msContentZooming",
+ "msConvertURL",
+ "msCrypto",
+ "msDoNotTrack",
+ "msElementsFromPoint",
+ "msElementsFromRect",
+ "msExitFullscreen",
+ "msExtendedCode",
+ "msFillRule",
+ "msFirstPaint",
+ "msFlex",
+ "msFlexAlign",
+ "msFlexDirection",
+ "msFlexFlow",
+ "msFlexItemAlign",
+ "msFlexLinePack",
+ "msFlexNegative",
+ "msFlexOrder",
+ "msFlexPack",
+ "msFlexPositive",
+ "msFlexPreferredSize",
+ "msFlexWrap",
+ "msFlowFrom",
+ "msFlowInto",
+ "msFontFeatureSettings",
+ "msFullscreenElement",
+ "msFullscreenEnabled",
+ "msGetInputContext",
+ "msGetRegionContent",
+ "msGetUntransformedBounds",
+ "msGraphicsTrustStatus",
+ "msGridColumn",
+ "msGridColumnAlign",
+ "msGridColumnSpan",
+ "msGridColumns",
+ "msGridRow",
+ "msGridRowAlign",
+ "msGridRowSpan",
+ "msGridRows",
+ "msHidden",
+ "msHighContrastAdjust",
+ "msHyphenateLimitChars",
+ "msHyphenateLimitLines",
+ "msHyphenateLimitZone",
+ "msHyphens",
+ "msImageSmoothingEnabled",
+ "msImeAlign",
+ "msIndexedDB",
+ "msInterpolationMode",
+ "msIsStaticHTML",
+ "msKeySystem",
+ "msKeys",
+ "msLaunchUri",
+ "msLockOrientation",
+ "msManipulationViewsEnabled",
+ "msMatchMedia",
+ "msMatchesSelector",
+ "msMaxTouchPoints",
+ "msOrientation",
+ "msOverflowStyle",
+ "msPerspective",
+ "msPerspectiveOrigin",
+ "msPlayToDisabled",
+ "msPlayToPreferredSourceUri",
+ "msPlayToPrimary",
+ "msPointerEnabled",
+ "msRegionOverflow",
+ "msReleasePointerCapture",
+ "msRequestAnimationFrame",
+ "msRequestFullscreen",
+ "msSaveBlob",
+ "msSaveOrOpenBlob",
+ "msScrollChaining",
+ "msScrollLimit",
+ "msScrollLimitXMax",
+ "msScrollLimitXMin",
+ "msScrollLimitYMax",
+ "msScrollLimitYMin",
+ "msScrollRails",
+ "msScrollSnapPointsX",
+ "msScrollSnapPointsY",
+ "msScrollSnapType",
+ "msScrollSnapX",
+ "msScrollSnapY",
+ "msScrollTranslation",
+ "msSetImmediate",
+ "msSetMediaKeys",
+ "msSetPointerCapture",
+ "msTextCombineHorizontal",
+ "msTextSizeAdjust",
+ "msToBlob",
+ "msTouchAction",
+ "msTouchSelect",
+ "msTraceAsyncCallbackCompleted",
+ "msTraceAsyncCallbackStarting",
+ "msTraceAsyncOperationCompleted",
+ "msTraceAsyncOperationStarting",
+ "msTransform",
+ "msTransformOrigin",
+ "msTransformStyle",
+ "msTransition",
+ "msTransitionDelay",
+ "msTransitionDuration",
+ "msTransitionProperty",
+ "msTransitionTimingFunction",
+ "msUnlockOrientation",
+ "msUpdateAsyncCallbackRelation",
+ "msUserSelect",
+ "msVisibilityState",
+ "msWrapFlow",
+ "msWrapMargin",
+ "msWrapThrough",
+ "msWriteProfilerMark",
+ "msZoom",
+ "msZoomTo",
+ "mt",
+ "mul",
+ "multiEntry",
+ "multiSelectionObj",
+ "multiline",
+ "multiple",
+ "multiply",
+ "multiplySelf",
+ "mutableFile",
+ "muted",
+ "n",
+ "name",
+ "nameProp",
+ "namedItem",
+ "namedRecordset",
+ "names",
+ "namespaceURI",
+ "namespaces",
+ "naturalHeight",
+ "naturalWidth",
+ "navigate",
+ "navigation",
+ "navigationMode",
+ "navigationPreload",
+ "navigationStart",
+ "navigator",
+ "near",
+ "nearestViewportElement",
+ "negative",
+ "negotiated",
+ "netscape",
+ "networkState",
+ "newScale",
+ "newTranslate",
+ "newURL",
+ "newValue",
+ "newValueSpecifiedUnits",
+ "newVersion",
+ "newhome",
+ "next",
+ "nextElementSibling",
+ "nextHopProtocol",
+ "nextNode",
+ "nextPage",
+ "nextSibling",
+ "nickname",
+ "noHref",
+ "noModule",
+ "noResize",
+ "noShade",
+ "noValidate",
+ "noWrap",
+ "node",
+ "nodeName",
+ "nodeType",
+ "nodeValue",
+ "nonce",
+ "normalize",
+ "normalizedPathSegList",
+ "notationName",
+ "notations",
+ "note",
+ "noteGrainOn",
+ "noteOff",
+ "noteOn",
+ "notify",
+ "now",
+ "numOctaves",
+ "number",
+ "numberOfChannels",
+ "numberOfInputs",
+ "numberOfItems",
+ "numberOfOutputs",
+ "numberValue",
+ "oMatchesSelector",
+ "object",
+ "object-fit",
+ "object-position",
+ "objectFit",
+ "objectPosition",
+ "objectStore",
+ "objectStoreNames",
+ "objectType",
+ "observe",
+ "of",
+ "offscreenBuffering",
+ "offset",
+ "offset-anchor",
+ "offset-distance",
+ "offset-path",
+ "offset-rotate",
+ "offsetAnchor",
+ "offsetDistance",
+ "offsetHeight",
+ "offsetLeft",
+ "offsetNode",
+ "offsetParent",
+ "offsetPath",
+ "offsetRotate",
+ "offsetTop",
+ "offsetWidth",
+ "offsetX",
+ "offsetY",
+ "ok",
+ "oldURL",
+ "oldValue",
+ "oldVersion",
+ "olderShadowRoot",
+ "onLine",
+ "onabort",
+ "onabsolutedeviceorientation",
+ "onactivate",
+ "onactive",
+ "onaddsourcebuffer",
+ "onaddstream",
+ "onaddtrack",
+ "onafterprint",
+ "onafterscriptexecute",
+ "onafterupdate",
+ "onanimationcancel",
+ "onanimationend",
+ "onanimationiteration",
+ "onanimationstart",
+ "onappinstalled",
+ "onaudioend",
+ "onaudioprocess",
+ "onaudiostart",
+ "onautocomplete",
+ "onautocompleteerror",
+ "onauxclick",
+ "onbeforeactivate",
+ "onbeforecopy",
+ "onbeforecut",
+ "onbeforedeactivate",
+ "onbeforeeditfocus",
+ "onbeforeinstallprompt",
+ "onbeforepaste",
+ "onbeforeprint",
+ "onbeforescriptexecute",
+ "onbeforeunload",
+ "onbeforeupdate",
+ "onbeforexrselect",
+ "onbegin",
+ "onblocked",
+ "onblur",
+ "onbounce",
+ "onboundary",
+ "onbufferedamountlow",
+ "oncached",
+ "oncancel",
+ "oncandidatewindowhide",
+ "oncandidatewindowshow",
+ "oncandidatewindowupdate",
+ "oncanplay",
+ "oncanplaythrough",
+ "once",
+ "oncellchange",
+ "onchange",
+ "oncharacteristicvaluechanged",
+ "onchargingchange",
+ "onchargingtimechange",
+ "onchecking",
+ "onclick",
+ "onclose",
+ "onclosing",
+ "oncompassneedscalibration",
+ "oncomplete",
+ "onconnect",
+ "onconnecting",
+ "onconnectionavailable",
+ "onconnectionstatechange",
+ "oncontextmenu",
+ "oncontrollerchange",
+ "oncontrolselect",
+ "oncopy",
+ "oncuechange",
+ "oncut",
+ "ondataavailable",
+ "ondatachannel",
+ "ondatasetchanged",
+ "ondatasetcomplete",
+ "ondblclick",
+ "ondeactivate",
+ "ondevicechange",
+ "ondevicelight",
+ "ondevicemotion",
+ "ondeviceorientation",
+ "ondeviceorientationabsolute",
+ "ondeviceproximity",
+ "ondischargingtimechange",
+ "ondisconnect",
+ "ondisplay",
+ "ondownloading",
+ "ondrag",
+ "ondragend",
+ "ondragenter",
+ "ondragexit",
+ "ondragleave",
+ "ondragover",
+ "ondragstart",
+ "ondrop",
+ "ondurationchange",
+ "onemptied",
+ "onencrypted",
+ "onend",
+ "onended",
+ "onenter",
+ "onenterpictureinpicture",
+ "onerror",
+ "onerrorupdate",
+ "onexit",
+ "onfilterchange",
+ "onfinish",
+ "onfocus",
+ "onfocusin",
+ "onfocusout",
+ "onformdata",
+ "onfreeze",
+ "onfullscreenchange",
+ "onfullscreenerror",
+ "ongatheringstatechange",
+ "ongattserverdisconnected",
+ "ongesturechange",
+ "ongestureend",
+ "ongesturestart",
+ "ongotpointercapture",
+ "onhashchange",
+ "onhelp",
+ "onicecandidate",
+ "onicecandidateerror",
+ "oniceconnectionstatechange",
+ "onicegatheringstatechange",
+ "oninactive",
+ "oninput",
+ "oninputsourceschange",
+ "oninvalid",
+ "onkeydown",
+ "onkeypress",
+ "onkeystatuseschange",
+ "onkeyup",
+ "onlanguagechange",
+ "onlayoutcomplete",
+ "onleavepictureinpicture",
+ "onlevelchange",
+ "onload",
+ "onloadeddata",
+ "onloadedmetadata",
+ "onloadend",
+ "onloading",
+ "onloadingdone",
+ "onloadingerror",
+ "onloadstart",
+ "onlosecapture",
+ "onlostpointercapture",
+ "only",
+ "onmark",
+ "onmessage",
+ "onmessageerror",
+ "onmidimessage",
+ "onmousedown",
+ "onmouseenter",
+ "onmouseleave",
+ "onmousemove",
+ "onmouseout",
+ "onmouseover",
+ "onmouseup",
+ "onmousewheel",
+ "onmove",
+ "onmoveend",
+ "onmovestart",
+ "onmozfullscreenchange",
+ "onmozfullscreenerror",
+ "onmozorientationchange",
+ "onmozpointerlockchange",
+ "onmozpointerlockerror",
+ "onmscontentzoom",
+ "onmsfullscreenchange",
+ "onmsfullscreenerror",
+ "onmsgesturechange",
+ "onmsgesturedoubletap",
+ "onmsgestureend",
+ "onmsgesturehold",
+ "onmsgesturestart",
+ "onmsgesturetap",
+ "onmsgotpointercapture",
+ "onmsinertiastart",
+ "onmslostpointercapture",
+ "onmsmanipulationstatechanged",
+ "onmsneedkey",
+ "onmsorientationchange",
+ "onmspointercancel",
+ "onmspointerdown",
+ "onmspointerenter",
+ "onmspointerhover",
+ "onmspointerleave",
+ "onmspointermove",
+ "onmspointerout",
+ "onmspointerover",
+ "onmspointerup",
+ "onmssitemodejumplistitemremoved",
+ "onmsthumbnailclick",
+ "onmute",
+ "onnegotiationneeded",
+ "onnomatch",
+ "onnoupdate",
+ "onobsolete",
+ "onoffline",
+ "ononline",
+ "onopen",
+ "onorientationchange",
+ "onpagechange",
+ "onpagehide",
+ "onpageshow",
+ "onpaste",
+ "onpause",
+ "onpayerdetailchange",
+ "onpaymentmethodchange",
+ "onplay",
+ "onplaying",
+ "onpluginstreamstart",
+ "onpointercancel",
+ "onpointerdown",
+ "onpointerenter",
+ "onpointerleave",
+ "onpointerlockchange",
+ "onpointerlockerror",
+ "onpointermove",
+ "onpointerout",
+ "onpointerover",
+ "onpointerrawupdate",
+ "onpointerup",
+ "onpopstate",
+ "onprocessorerror",
+ "onprogress",
+ "onpropertychange",
+ "onratechange",
+ "onreading",
+ "onreadystatechange",
+ "onrejectionhandled",
+ "onrelease",
+ "onremove",
+ "onremovesourcebuffer",
+ "onremovestream",
+ "onremovetrack",
+ "onrepeat",
+ "onreset",
+ "onresize",
+ "onresizeend",
+ "onresizestart",
+ "onresourcetimingbufferfull",
+ "onresult",
+ "onresume",
+ "onrowenter",
+ "onrowexit",
+ "onrowsdelete",
+ "onrowsinserted",
+ "onscroll",
+ "onsearch",
+ "onsecuritypolicyviolation",
+ "onseeked",
+ "onseeking",
+ "onselect",
+ "onselectedcandidatepairchange",
+ "onselectend",
+ "onselectionchange",
+ "onselectstart",
+ "onshippingaddresschange",
+ "onshippingoptionchange",
+ "onshow",
+ "onsignalingstatechange",
+ "onsoundend",
+ "onsoundstart",
+ "onsourceclose",
+ "onsourceclosed",
+ "onsourceended",
+ "onsourceopen",
+ "onspeechend",
+ "onspeechstart",
+ "onsqueeze",
+ "onsqueezeend",
+ "onsqueezestart",
+ "onstalled",
+ "onstart",
+ "onstatechange",
+ "onstop",
+ "onstorage",
+ "onstoragecommit",
+ "onsubmit",
+ "onsuccess",
+ "onsuspend",
+ "onterminate",
+ "ontextinput",
+ "ontimeout",
+ "ontimeupdate",
+ "ontoggle",
+ "ontonechange",
+ "ontouchcancel",
+ "ontouchend",
+ "ontouchmove",
+ "ontouchstart",
+ "ontrack",
+ "ontransitioncancel",
+ "ontransitionend",
+ "ontransitionrun",
+ "ontransitionstart",
+ "onunhandledrejection",
+ "onunload",
+ "onunmute",
+ "onupdate",
+ "onupdateend",
+ "onupdatefound",
+ "onupdateready",
+ "onupdatestart",
+ "onupgradeneeded",
+ "onuserproximity",
+ "onversionchange",
+ "onvisibilitychange",
+ "onvoiceschanged",
+ "onvolumechange",
+ "onvrdisplayactivate",
+ "onvrdisplayconnect",
+ "onvrdisplaydeactivate",
+ "onvrdisplaydisconnect",
+ "onvrdisplaypresentchange",
+ "onwaiting",
+ "onwaitingforkey",
+ "onwarning",
+ "onwebkitanimationend",
+ "onwebkitanimationiteration",
+ "onwebkitanimationstart",
+ "onwebkitcurrentplaybacktargetiswirelesschanged",
+ "onwebkitfullscreenchange",
+ "onwebkitfullscreenerror",
+ "onwebkitkeyadded",
+ "onwebkitkeyerror",
+ "onwebkitkeymessage",
+ "onwebkitneedkey",
+ "onwebkitorientationchange",
+ "onwebkitplaybacktargetavailabilitychanged",
+ "onwebkitpointerlockchange",
+ "onwebkitpointerlockerror",
+ "onwebkitresourcetimingbufferfull",
+ "onwebkittransitionend",
+ "onwheel",
+ "onzoom",
+ "opacity",
+ "open",
+ "openCursor",
+ "openDatabase",
+ "openKeyCursor",
+ "opened",
+ "opener",
+ "opera",
+ "operationType",
+ "operator",
+ "opr",
+ "optimum",
+ "options",
+ "or",
+ "order",
+ "orderX",
+ "orderY",
+ "ordered",
+ "org",
+ "organization",
+ "orient",
+ "orientAngle",
+ "orientType",
+ "orientation",
+ "orientationX",
+ "orientationY",
+ "orientationZ",
+ "origin",
+ "originalPolicy",
+ "originalTarget",
+ "orphans",
+ "oscpu",
+ "outerHTML",
+ "outerHeight",
+ "outerText",
+ "outerWidth",
+ "outline",
+ "outline-color",
+ "outline-offset",
+ "outline-style",
+ "outline-width",
+ "outlineColor",
+ "outlineOffset",
+ "outlineStyle",
+ "outlineWidth",
+ "outputBuffer",
+ "outputLatency",
+ "outputs",
+ "overflow",
+ "overflow-anchor",
+ "overflow-block",
+ "overflow-inline",
+ "overflow-wrap",
+ "overflow-x",
+ "overflow-y",
+ "overflowAnchor",
+ "overflowBlock",
+ "overflowInline",
+ "overflowWrap",
+ "overflowX",
+ "overflowY",
+ "overrideMimeType",
+ "oversample",
+ "overscroll-behavior",
+ "overscroll-behavior-block",
+ "overscroll-behavior-inline",
+ "overscroll-behavior-x",
+ "overscroll-behavior-y",
+ "overscrollBehavior",
+ "overscrollBehaviorBlock",
+ "overscrollBehaviorInline",
+ "overscrollBehaviorX",
+ "overscrollBehaviorY",
+ "ownKeys",
+ "ownerDocument",
+ "ownerElement",
+ "ownerNode",
+ "ownerRule",
+ "ownerSVGElement",
+ "owningElement",
+ "p1",
+ "p2",
+ "p3",
+ "p4",
+ "packetSize",
+ "packets",
+ "pad",
+ "padEnd",
+ "padStart",
+ "padding",
+ "padding-block",
+ "padding-block-end",
+ "padding-block-start",
+ "padding-bottom",
+ "padding-inline",
+ "padding-inline-end",
+ "padding-inline-start",
+ "padding-left",
+ "padding-right",
+ "padding-top",
+ "paddingBlock",
+ "paddingBlockEnd",
+ "paddingBlockStart",
+ "paddingBottom",
+ "paddingInline",
+ "paddingInlineEnd",
+ "paddingInlineStart",
+ "paddingLeft",
+ "paddingRight",
+ "paddingTop",
+ "page",
+ "page-break-after",
+ "page-break-before",
+ "page-break-inside",
+ "pageBreakAfter",
+ "pageBreakBefore",
+ "pageBreakInside",
+ "pageCount",
+ "pageLeft",
+ "pageTop",
+ "pageX",
+ "pageXOffset",
+ "pageY",
+ "pageYOffset",
+ "pages",
+ "paint-order",
+ "paintOrder",
+ "paintRequests",
+ "paintType",
+ "paintWorklet",
+ "palette",
+ "pan",
+ "panningModel",
+ "parameters",
+ "parent",
+ "parentElement",
+ "parentNode",
+ "parentRule",
+ "parentStyleSheet",
+ "parentTextEdit",
+ "parentWindow",
+ "parse",
+ "parseAll",
+ "parseFloat",
+ "parseFromString",
+ "parseInt",
+ "part",
+ "participants",
+ "passive",
+ "password",
+ "pasteHTML",
+ "path",
+ "pathLength",
+ "pathSegList",
+ "pathSegType",
+ "pathSegTypeAsLetter",
+ "pathname",
+ "pattern",
+ "patternContentUnits",
+ "patternMismatch",
+ "patternTransform",
+ "patternUnits",
+ "pause",
+ "pauseAnimations",
+ "pauseOnExit",
+ "pauseProfilers",
+ "pauseTransformFeedback",
+ "paused",
+ "payerEmail",
+ "payerName",
+ "payerPhone",
+ "paymentManager",
+ "pc",
+ "peerIdentity",
+ "pending",
+ "pendingLocalDescription",
+ "pendingRemoteDescription",
+ "percent",
+ "performance",
+ "periodicSync",
+ "permission",
+ "permissionState",
+ "permissions",
+ "persist",
+ "persisted",
+ "personalbar",
+ "perspective",
+ "perspective-origin",
+ "perspectiveOrigin",
+ "phone",
+ "phoneticFamilyName",
+ "phoneticGivenName",
+ "photo",
+ "pictureInPictureElement",
+ "pictureInPictureEnabled",
+ "pictureInPictureWindow",
+ "ping",
+ "pipeThrough",
+ "pipeTo",
+ "pitch",
+ "pixelBottom",
+ "pixelDepth",
+ "pixelHeight",
+ "pixelLeft",
+ "pixelRight",
+ "pixelStorei",
+ "pixelTop",
+ "pixelUnitToMillimeterX",
+ "pixelUnitToMillimeterY",
+ "pixelWidth",
+ "place-content",
+ "place-items",
+ "place-self",
+ "placeContent",
+ "placeItems",
+ "placeSelf",
+ "placeholder",
+ "platform",
+ "platforms",
+ "play",
+ "playEffect",
+ "playState",
+ "playbackRate",
+ "playbackState",
+ "playbackTime",
+ "played",
+ "playoutDelayHint",
+ "playsInline",
+ "plugins",
+ "pluginspage",
+ "pname",
+ "pointer-events",
+ "pointerBeforeReferenceNode",
+ "pointerEnabled",
+ "pointerEvents",
+ "pointerId",
+ "pointerLockElement",
+ "pointerType",
+ "points",
+ "pointsAtX",
+ "pointsAtY",
+ "pointsAtZ",
+ "polygonOffset",
+ "pop",
+ "populateMatrix",
+ "popupWindowFeatures",
+ "popupWindowName",
+ "popupWindowURI",
+ "port",
+ "port1",
+ "port2",
+ "ports",
+ "posBottom",
+ "posHeight",
+ "posLeft",
+ "posRight",
+ "posTop",
+ "posWidth",
+ "pose",
+ "position",
+ "positionAlign",
+ "positionX",
+ "positionY",
+ "positionZ",
+ "postError",
+ "postMessage",
+ "postalCode",
+ "poster",
+ "pow",
+ "powerEfficient",
+ "powerOff",
+ "preMultiplySelf",
+ "precision",
+ "preferredStyleSheetSet",
+ "preferredStylesheetSet",
+ "prefix",
+ "preload",
+ "prepend",
+ "presentation",
+ "preserveAlpha",
+ "preserveAspectRatio",
+ "preserveAspectRatioString",
+ "pressed",
+ "pressure",
+ "prevValue",
+ "preventDefault",
+ "preventExtensions",
+ "preventSilentAccess",
+ "previousElementSibling",
+ "previousNode",
+ "previousPage",
+ "previousRect",
+ "previousScale",
+ "previousSibling",
+ "previousTranslate",
+ "primaryKey",
+ "primitiveType",
+ "primitiveUnits",
+ "principals",
+ "print",
+ "priority",
+ "privateKey",
+ "probablySupportsContext",
+ "process",
+ "processIceMessage",
+ "processingEnd",
+ "processingStart",
+ "product",
+ "productId",
+ "productName",
+ "productSub",
+ "profile",
+ "profileEnd",
+ "profiles",
+ "projectionMatrix",
+ "promise",
+ "prompt",
+ "properties",
+ "propertyIsEnumerable",
+ "propertyName",
+ "protocol",
+ "protocolLong",
+ "prototype",
+ "provider",
+ "pseudoClass",
+ "pseudoElement",
+ "pt",
+ "publicId",
+ "publicKey",
+ "published",
+ "pulse",
+ "push",
+ "pushManager",
+ "pushNotification",
+ "pushState",
+ "put",
+ "putImageData",
+ "px",
+ "quadraticCurveTo",
+ "qualifier",
+ "quaternion",
+ "query",
+ "queryCommandEnabled",
+ "queryCommandIndeterm",
+ "queryCommandState",
+ "queryCommandSupported",
+ "queryCommandText",
+ "queryCommandValue",
+ "querySelector",
+ "querySelectorAll",
+ "queueMicrotask",
+ "quote",
+ "quotes",
+ "r",
+ "r1",
+ "r2",
+ "race",
+ "rad",
+ "radiogroup",
+ "radiusX",
+ "radiusY",
+ "random",
+ "range",
+ "rangeCount",
+ "rangeMax",
+ "rangeMin",
+ "rangeOffset",
+ "rangeOverflow",
+ "rangeParent",
+ "rangeUnderflow",
+ "rate",
+ "ratio",
+ "raw",
+ "rawId",
+ "read",
+ "readAsArrayBuffer",
+ "readAsBinaryString",
+ "readAsBlob",
+ "readAsDataURL",
+ "readAsText",
+ "readBuffer",
+ "readEntries",
+ "readOnly",
+ "readPixels",
+ "readReportRequested",
+ "readText",
+ "readValue",
+ "readable",
+ "ready",
+ "readyState",
+ "reason",
+ "reboot",
+ "receivedAlert",
+ "receiver",
+ "receivers",
+ "recipient",
+ "reconnect",
+ "recordNumber",
+ "recordsAvailable",
+ "recordset",
+ "rect",
+ "red",
+ "redEyeReduction",
+ "redirect",
+ "redirectCount",
+ "redirectEnd",
+ "redirectStart",
+ "redirected",
+ "reduce",
+ "reduceRight",
+ "reduction",
+ "refDistance",
+ "refX",
+ "refY",
+ "referenceNode",
+ "referenceSpace",
+ "referrer",
+ "referrerPolicy",
+ "refresh",
+ "region",
+ "regionAnchorX",
+ "regionAnchorY",
+ "regionId",
+ "regions",
+ "register",
+ "registerContentHandler",
+ "registerElement",
+ "registerProperty",
+ "registerProtocolHandler",
+ "reject",
+ "rel",
+ "relList",
+ "relatedAddress",
+ "relatedNode",
+ "relatedPort",
+ "relatedTarget",
+ "release",
+ "releaseCapture",
+ "releaseEvents",
+ "releaseInterface",
+ "releaseLock",
+ "releasePointerCapture",
+ "releaseShaderCompiler",
+ "reliable",
+ "reliableWrite",
+ "reload",
+ "rem",
+ "remainingSpace",
+ "remote",
+ "remoteDescription",
+ "remove",
+ "removeAllRanges",
+ "removeAttribute",
+ "removeAttributeNS",
+ "removeAttributeNode",
+ "removeBehavior",
+ "removeChild",
+ "removeCue",
+ "removeEventListener",
+ "removeFilter",
+ "removeImport",
+ "removeItem",
+ "removeListener",
+ "removeNamedItem",
+ "removeNamedItemNS",
+ "removeNode",
+ "removeParameter",
+ "removeProperty",
+ "removeRange",
+ "removeRegion",
+ "removeRule",
+ "removeSiteSpecificTrackingException",
+ "removeSourceBuffer",
+ "removeStream",
+ "removeTrack",
+ "removeVariable",
+ "removeWakeLockListener",
+ "removeWebWideTrackingException",
+ "removed",
+ "removedNodes",
+ "renderHeight",
+ "renderState",
+ "renderTime",
+ "renderWidth",
+ "renderbufferStorage",
+ "renderbufferStorageMultisample",
+ "renderedBuffer",
+ "renderingMode",
+ "renotify",
+ "repeat",
+ "replace",
+ "replaceAdjacentText",
+ "replaceAll",
+ "replaceChild",
+ "replaceChildren",
+ "replaceData",
+ "replaceId",
+ "replaceItem",
+ "replaceNode",
+ "replaceState",
+ "replaceSync",
+ "replaceTrack",
+ "replaceWholeText",
+ "replaceWith",
+ "reportValidity",
+ "request",
+ "requestAnimationFrame",
+ "requestAutocomplete",
+ "requestData",
+ "requestDevice",
+ "requestFrame",
+ "requestFullscreen",
+ "requestHitTestSource",
+ "requestHitTestSourceForTransientInput",
+ "requestId",
+ "requestIdleCallback",
+ "requestMIDIAccess",
+ "requestMediaKeySystemAccess",
+ "requestPermission",
+ "requestPictureInPicture",
+ "requestPointerLock",
+ "requestPresent",
+ "requestReferenceSpace",
+ "requestSession",
+ "requestStart",
+ "requestStorageAccess",
+ "requestSubmit",
+ "requestVideoFrameCallback",
+ "requestingWindow",
+ "requireInteraction",
+ "required",
+ "requiredExtensions",
+ "requiredFeatures",
+ "reset",
+ "resetPose",
+ "resetTransform",
+ "resize",
+ "resizeBy",
+ "resizeTo",
+ "resolve",
+ "response",
+ "responseBody",
+ "responseEnd",
+ "responseReady",
+ "responseStart",
+ "responseText",
+ "responseType",
+ "responseURL",
+ "responseXML",
+ "restartIce",
+ "restore",
+ "result",
+ "resultIndex",
+ "resultType",
+ "results",
+ "resume",
+ "resumeProfilers",
+ "resumeTransformFeedback",
+ "retry",
+ "return",
+ "returnValue",
+ "rev",
+ "reverse",
+ "reversed",
+ "revocable",
+ "revokeObjectURL",
+ "rgbColor",
+ "right",
+ "rightContext",
+ "rightDegrees",
+ "rightMargin",
+ "rightProjectionMatrix",
+ "rightViewMatrix",
+ "role",
+ "rolloffFactor",
+ "root",
+ "rootBounds",
+ "rootElement",
+ "rootMargin",
+ "rotate",
+ "rotateAxisAngle",
+ "rotateAxisAngleSelf",
+ "rotateFromVector",
+ "rotateFromVectorSelf",
+ "rotateSelf",
+ "rotation",
+ "rotationAngle",
+ "rotationRate",
+ "round",
+ "row-gap",
+ "rowGap",
+ "rowIndex",
+ "rowSpan",
+ "rows",
+ "rtcpTransport",
+ "rtt",
+ "ruby-align",
+ "ruby-position",
+ "rubyAlign",
+ "rubyOverhang",
+ "rubyPosition",
+ "rules",
+ "runtime",
+ "runtimeStyle",
+ "rx",
+ "ry",
+ "s",
+ "safari",
+ "sample",
+ "sampleCoverage",
+ "sampleRate",
+ "samplerParameterf",
+ "samplerParameteri",
+ "sandbox",
+ "save",
+ "saveData",
+ "scale",
+ "scale3d",
+ "scale3dSelf",
+ "scaleNonUniform",
+ "scaleNonUniformSelf",
+ "scaleSelf",
+ "scheme",
+ "scissor",
+ "scope",
+ "scopeName",
+ "scoped",
+ "screen",
+ "screenBrightness",
+ "screenEnabled",
+ "screenLeft",
+ "screenPixelToMillimeterX",
+ "screenPixelToMillimeterY",
+ "screenTop",
+ "screenX",
+ "screenY",
+ "scriptURL",
+ "scripts",
+ "scroll",
+ "scroll-behavior",
+ "scroll-margin",
+ "scroll-margin-block",
+ "scroll-margin-block-end",
+ "scroll-margin-block-start",
+ "scroll-margin-bottom",
+ "scroll-margin-inline",
+ "scroll-margin-inline-end",
+ "scroll-margin-inline-start",
+ "scroll-margin-left",
+ "scroll-margin-right",
+ "scroll-margin-top",
+ "scroll-padding",
+ "scroll-padding-block",
+ "scroll-padding-block-end",
+ "scroll-padding-block-start",
+ "scroll-padding-bottom",
+ "scroll-padding-inline",
+ "scroll-padding-inline-end",
+ "scroll-padding-inline-start",
+ "scroll-padding-left",
+ "scroll-padding-right",
+ "scroll-padding-top",
+ "scroll-snap-align",
+ "scroll-snap-type",
+ "scrollAmount",
+ "scrollBehavior",
+ "scrollBy",
+ "scrollByLines",
+ "scrollByPages",
+ "scrollDelay",
+ "scrollHeight",
+ "scrollIntoView",
+ "scrollIntoViewIfNeeded",
+ "scrollLeft",
+ "scrollLeftMax",
+ "scrollMargin",
+ "scrollMarginBlock",
+ "scrollMarginBlockEnd",
+ "scrollMarginBlockStart",
+ "scrollMarginBottom",
+ "scrollMarginInline",
+ "scrollMarginInlineEnd",
+ "scrollMarginInlineStart",
+ "scrollMarginLeft",
+ "scrollMarginRight",
+ "scrollMarginTop",
+ "scrollMaxX",
+ "scrollMaxY",
+ "scrollPadding",
+ "scrollPaddingBlock",
+ "scrollPaddingBlockEnd",
+ "scrollPaddingBlockStart",
+ "scrollPaddingBottom",
+ "scrollPaddingInline",
+ "scrollPaddingInlineEnd",
+ "scrollPaddingInlineStart",
+ "scrollPaddingLeft",
+ "scrollPaddingRight",
+ "scrollPaddingTop",
+ "scrollRestoration",
+ "scrollSnapAlign",
+ "scrollSnapType",
+ "scrollTo",
+ "scrollTop",
+ "scrollTopMax",
+ "scrollWidth",
+ "scrollX",
+ "scrollY",
+ "scrollbar-color",
+ "scrollbar-width",
+ "scrollbar3dLightColor",
+ "scrollbarArrowColor",
+ "scrollbarBaseColor",
+ "scrollbarColor",
+ "scrollbarDarkShadowColor",
+ "scrollbarFaceColor",
+ "scrollbarHighlightColor",
+ "scrollbarShadowColor",
+ "scrollbarTrackColor",
+ "scrollbarWidth",
+ "scrollbars",
+ "scrolling",
+ "scrollingElement",
+ "sctp",
+ "sctpCauseCode",
+ "sdp",
+ "sdpLineNumber",
+ "sdpMLineIndex",
+ "sdpMid",
+ "seal",
+ "search",
+ "searchBox",
+ "searchBoxJavaBridge_",
+ "searchParams",
+ "sectionRowIndex",
+ "secureConnectionStart",
+ "security",
+ "seed",
+ "seekToNextFrame",
+ "seekable",
+ "seeking",
+ "select",
+ "selectAllChildren",
+ "selectAlternateInterface",
+ "selectConfiguration",
+ "selectNode",
+ "selectNodeContents",
+ "selectNodes",
+ "selectSingleNode",
+ "selectSubString",
+ "selected",
+ "selectedIndex",
+ "selectedOptions",
+ "selectedStyleSheetSet",
+ "selectedStylesheetSet",
+ "selection",
+ "selectionDirection",
+ "selectionEnd",
+ "selectionStart",
+ "selector",
+ "selectorText",
+ "self",
+ "send",
+ "sendAsBinary",
+ "sendBeacon",
+ "sender",
+ "sentAlert",
+ "sentTimestamp",
+ "separator",
+ "serialNumber",
+ "serializeToString",
+ "serverTiming",
+ "service",
+ "serviceWorker",
+ "session",
+ "sessionId",
+ "sessionStorage",
+ "set",
+ "setActionHandler",
+ "setActive",
+ "setAlpha",
+ "setAppBadge",
+ "setAttribute",
+ "setAttributeNS",
+ "setAttributeNode",
+ "setAttributeNodeNS",
+ "setBaseAndExtent",
+ "setBigInt64",
+ "setBigUint64",
+ "setBingCurrentSearchDefault",
+ "setCapture",
+ "setCodecPreferences",
+ "setColor",
+ "setCompositeOperation",
+ "setConfiguration",
+ "setCurrentTime",
+ "setCustomValidity",
+ "setData",
+ "setDate",
+ "setDragImage",
+ "setEnd",
+ "setEndAfter",
+ "setEndBefore",
+ "setEndPoint",
+ "setFillColor",
+ "setFilterRes",
+ "setFloat32",
+ "setFloat64",
+ "setFloatValue",
+ "setFormValue",
+ "setFullYear",
+ "setHeaderValue",
+ "setHours",
+ "setIdentityProvider",
+ "setImmediate",
+ "setInt16",
+ "setInt32",
+ "setInt8",
+ "setInterval",
+ "setItem",
+ "setKeyframes",
+ "setLineCap",
+ "setLineDash",
+ "setLineJoin",
+ "setLineWidth",
+ "setLiveSeekableRange",
+ "setLocalDescription",
+ "setMatrix",
+ "setMatrixValue",
+ "setMediaKeys",
+ "setMilliseconds",
+ "setMinutes",
+ "setMiterLimit",
+ "setMonth",
+ "setNamedItem",
+ "setNamedItemNS",
+ "setNonUserCodeExceptions",
+ "setOrientToAngle",
+ "setOrientToAuto",
+ "setOrientation",
+ "setOverrideHistoryNavigationMode",
+ "setPaint",
+ "setParameter",
+ "setParameters",
+ "setPeriodicWave",
+ "setPointerCapture",
+ "setPosition",
+ "setPositionState",
+ "setPreference",
+ "setProperty",
+ "setPrototypeOf",
+ "setRGBColor",
+ "setRGBColorICCColor",
+ "setRadius",
+ "setRangeText",
+ "setRemoteDescription",
+ "setRequestHeader",
+ "setResizable",
+ "setResourceTimingBufferSize",
+ "setRotate",
+ "setScale",
+ "setSeconds",
+ "setSelectionRange",
+ "setServerCertificate",
+ "setShadow",
+ "setSinkId",
+ "setSkewX",
+ "setSkewY",
+ "setStart",
+ "setStartAfter",
+ "setStartBefore",
+ "setStdDeviation",
+ "setStreams",
+ "setStringValue",
+ "setStrokeColor",
+ "setSuggestResult",
+ "setTargetAtTime",
+ "setTargetValueAtTime",
+ "setTime",
+ "setTimeout",
+ "setTransform",
+ "setTranslate",
+ "setUTCDate",
+ "setUTCFullYear",
+ "setUTCHours",
+ "setUTCMilliseconds",
+ "setUTCMinutes",
+ "setUTCMonth",
+ "setUTCSeconds",
+ "setUint16",
+ "setUint32",
+ "setUint8",
+ "setUri",
+ "setValidity",
+ "setValueAtTime",
+ "setValueCurveAtTime",
+ "setVariable",
+ "setVelocity",
+ "setVersion",
+ "setYear",
+ "settingName",
+ "settingValue",
+ "sex",
+ "shaderSource",
+ "shadowBlur",
+ "shadowColor",
+ "shadowOffsetX",
+ "shadowOffsetY",
+ "shadowRoot",
+ "shape",
+ "shape-image-threshold",
+ "shape-margin",
+ "shape-outside",
+ "shape-rendering",
+ "shapeImageThreshold",
+ "shapeMargin",
+ "shapeOutside",
+ "shapeRendering",
+ "sheet",
+ "shift",
+ "shiftKey",
+ "shiftLeft",
+ "shippingAddress",
+ "shippingOption",
+ "shippingType",
+ "show",
+ "showHelp",
+ "showModal",
+ "showModalDialog",
+ "showModelessDialog",
+ "showNotification",
+ "sidebar",
+ "sign",
+ "signal",
+ "signalingState",
+ "signature",
+ "silent",
+ "sin",
+ "singleNodeValue",
+ "sinh",
+ "sinkId",
+ "sittingToStandingTransform",
+ "size",
+ "sizeToContent",
+ "sizeX",
+ "sizeZ",
+ "sizes",
+ "skewX",
+ "skewXSelf",
+ "skewY",
+ "skewYSelf",
+ "slice",
+ "slope",
+ "slot",
+ "small",
+ "smil",
+ "smooth",
+ "smoothingTimeConstant",
+ "snapToLines",
+ "snapshotItem",
+ "snapshotLength",
+ "some",
+ "sort",
+ "sortingCode",
+ "source",
+ "sourceBuffer",
+ "sourceBuffers",
+ "sourceCapabilities",
+ "sourceFile",
+ "sourceIndex",
+ "sources",
+ "spacing",
+ "span",
+ "speak",
+ "speakAs",
+ "speaking",
+ "species",
+ "specified",
+ "specularConstant",
+ "specularExponent",
+ "speechSynthesis",
+ "speed",
+ "speedOfSound",
+ "spellcheck",
+ "splice",
+ "split",
+ "splitText",
+ "spreadMethod",
+ "sqrt",
+ "src",
+ "srcElement",
+ "srcFilter",
+ "srcObject",
+ "srcUrn",
+ "srcdoc",
+ "srclang",
+ "srcset",
+ "stack",
+ "stackTraceLimit",
+ "stacktrace",
+ "stageParameters",
+ "standalone",
+ "standby",
+ "start",
+ "startContainer",
+ "startIce",
+ "startMessages",
+ "startNotifications",
+ "startOffset",
+ "startProfiling",
+ "startRendering",
+ "startShark",
+ "startTime",
+ "startsWith",
+ "state",
+ "status",
+ "statusCode",
+ "statusMessage",
+ "statusText",
+ "statusbar",
+ "stdDeviationX",
+ "stdDeviationY",
+ "stencilFunc",
+ "stencilFuncSeparate",
+ "stencilMask",
+ "stencilMaskSeparate",
+ "stencilOp",
+ "stencilOpSeparate",
+ "step",
+ "stepDown",
+ "stepMismatch",
+ "stepUp",
+ "sticky",
+ "stitchTiles",
+ "stop",
+ "stop-color",
+ "stop-opacity",
+ "stopColor",
+ "stopImmediatePropagation",
+ "stopNotifications",
+ "stopOpacity",
+ "stopProfiling",
+ "stopPropagation",
+ "stopShark",
+ "stopped",
+ "storage",
+ "storageArea",
+ "storageName",
+ "storageStatus",
+ "store",
+ "storeSiteSpecificTrackingException",
+ "storeWebWideTrackingException",
+ "stpVersion",
+ "stream",
+ "streams",
+ "stretch",
+ "strike",
+ "string",
+ "stringValue",
+ "stringify",
+ "stroke",
+ "stroke-dasharray",
+ "stroke-dashoffset",
+ "stroke-linecap",
+ "stroke-linejoin",
+ "stroke-miterlimit",
+ "stroke-opacity",
+ "stroke-width",
+ "strokeDasharray",
+ "strokeDashoffset",
+ "strokeLinecap",
+ "strokeLinejoin",
+ "strokeMiterlimit",
+ "strokeOpacity",
+ "strokeRect",
+ "strokeStyle",
+ "strokeText",
+ "strokeWidth",
+ "style",
+ "styleFloat",
+ "styleMap",
+ "styleMedia",
+ "styleSheet",
+ "styleSheetSets",
+ "styleSheets",
+ "sub",
+ "subarray",
+ "subject",
+ "submit",
+ "submitFrame",
+ "submitter",
+ "subscribe",
+ "substr",
+ "substring",
+ "substringData",
+ "subtle",
+ "subtree",
+ "suffix",
+ "suffixes",
+ "summary",
+ "sup",
+ "supported",
+ "supportedContentEncodings",
+ "supportedEntryTypes",
+ "supports",
+ "supportsSession",
+ "surfaceScale",
+ "surroundContents",
+ "suspend",
+ "suspendRedraw",
+ "swapCache",
+ "swapNode",
+ "sweepFlag",
+ "symbols",
+ "sync",
+ "sysexEnabled",
+ "system",
+ "systemCode",
+ "systemId",
+ "systemLanguage",
+ "systemXDPI",
+ "systemYDPI",
+ "tBodies",
+ "tFoot",
+ "tHead",
+ "tabIndex",
+ "table",
+ "table-layout",
+ "tableLayout",
+ "tableValues",
+ "tag",
+ "tagName",
+ "tagUrn",
+ "tags",
+ "taintEnabled",
+ "takePhoto",
+ "takeRecords",
+ "tan",
+ "tangentialPressure",
+ "tanh",
+ "target",
+ "targetElement",
+ "targetRayMode",
+ "targetRaySpace",
+ "targetTouches",
+ "targetX",
+ "targetY",
+ "tcpType",
+ "tee",
+ "tel",
+ "terminate",
+ "test",
+ "texImage2D",
+ "texImage3D",
+ "texParameterf",
+ "texParameteri",
+ "texStorage2D",
+ "texStorage3D",
+ "texSubImage2D",
+ "texSubImage3D",
+ "text",
+ "text-align",
+ "text-align-last",
+ "text-anchor",
+ "text-combine-upright",
+ "text-decoration",
+ "text-decoration-color",
+ "text-decoration-line",
+ "text-decoration-skip-ink",
+ "text-decoration-style",
+ "text-decoration-thickness",
+ "text-emphasis",
+ "text-emphasis-color",
+ "text-emphasis-position",
+ "text-emphasis-style",
+ "text-indent",
+ "text-justify",
+ "text-orientation",
+ "text-overflow",
+ "text-rendering",
+ "text-shadow",
+ "text-transform",
+ "text-underline-offset",
+ "text-underline-position",
+ "textAlign",
+ "textAlignLast",
+ "textAnchor",
+ "textAutospace",
+ "textBaseline",
+ "textCombineUpright",
+ "textContent",
+ "textDecoration",
+ "textDecorationBlink",
+ "textDecorationColor",
+ "textDecorationLine",
+ "textDecorationLineThrough",
+ "textDecorationNone",
+ "textDecorationOverline",
+ "textDecorationSkipInk",
+ "textDecorationStyle",
+ "textDecorationThickness",
+ "textDecorationUnderline",
+ "textEmphasis",
+ "textEmphasisColor",
+ "textEmphasisPosition",
+ "textEmphasisStyle",
+ "textIndent",
+ "textJustify",
+ "textJustifyTrim",
+ "textKashida",
+ "textKashidaSpace",
+ "textLength",
+ "textOrientation",
+ "textOverflow",
+ "textRendering",
+ "textShadow",
+ "textTracks",
+ "textTransform",
+ "textUnderlineOffset",
+ "textUnderlinePosition",
+ "then",
+ "threadId",
+ "threshold",
+ "thresholds",
+ "throw",
+ "tiltX",
+ "tiltY",
+ "time",
+ "timeEnd",
+ "timeLog",
+ "timeOrigin",
+ "timeRemaining",
+ "timeStamp",
+ "timecode",
+ "timeline",
+ "timelineTime",
+ "timeout",
+ "timestamp",
+ "timestampOffset",
+ "timing",
+ "title",
+ "to",
+ "toArray",
+ "toBlob",
+ "toDataURL",
+ "toDateString",
+ "toElement",
+ "toExponential",
+ "toFixed",
+ "toFloat32Array",
+ "toFloat64Array",
+ "toGMTString",
+ "toISOString",
+ "toJSON",
+ "toLocaleDateString",
+ "toLocaleFormat",
+ "toLocaleLowerCase",
+ "toLocaleString",
+ "toLocaleTimeString",
+ "toLocaleUpperCase",
+ "toLowerCase",
+ "toMatrix",
+ "toMethod",
+ "toPrecision",
+ "toPrimitive",
+ "toSdp",
+ "toSource",
+ "toStaticHTML",
+ "toString",
+ "toStringTag",
+ "toSum",
+ "toTimeString",
+ "toUTCString",
+ "toUpperCase",
+ "toggle",
+ "toggleAttribute",
+ "toggleLongPressEnabled",
+ "tone",
+ "toneBuffer",
+ "tooLong",
+ "tooShort",
+ "toolbar",
+ "top",
+ "topMargin",
+ "total",
+ "totalFrameDelay",
+ "totalVideoFrames",
+ "touch-action",
+ "touchAction",
+ "touched",
+ "touches",
+ "trace",
+ "track",
+ "trackVisibility",
+ "transaction",
+ "transactions",
+ "transceiver",
+ "transferControlToOffscreen",
+ "transferFromImageBitmap",
+ "transferImageBitmap",
+ "transferIn",
+ "transferOut",
+ "transferSize",
+ "transferToImageBitmap",
+ "transform",
+ "transform-box",
+ "transform-origin",
+ "transform-style",
+ "transformBox",
+ "transformFeedbackVaryings",
+ "transformOrigin",
+ "transformPoint",
+ "transformString",
+ "transformStyle",
+ "transformToDocument",
+ "transformToFragment",
+ "transition",
+ "transition-delay",
+ "transition-duration",
+ "transition-property",
+ "transition-timing-function",
+ "transitionDelay",
+ "transitionDuration",
+ "transitionProperty",
+ "transitionTimingFunction",
+ "translate",
+ "translateSelf",
+ "translationX",
+ "translationY",
+ "transport",
+ "trim",
+ "trimEnd",
+ "trimLeft",
+ "trimRight",
+ "trimStart",
+ "trueSpeed",
+ "trunc",
+ "truncate",
+ "trustedTypes",
+ "turn",
+ "twist",
+ "type",
+ "typeDetail",
+ "typeMismatch",
+ "typeMustMatch",
+ "types",
+ "u2f",
+ "ubound",
+ "uint16",
+ "uint32",
+ "uint8",
+ "uint8Clamped",
+ "undefined",
+ "unescape",
+ "uneval",
+ "unicode",
+ "unicode-bidi",
+ "unicodeBidi",
+ "unicodeRange",
+ "uniform1f",
+ "uniform1fv",
+ "uniform1i",
+ "uniform1iv",
+ "uniform1ui",
+ "uniform1uiv",
+ "uniform2f",
+ "uniform2fv",
+ "uniform2i",
+ "uniform2iv",
+ "uniform2ui",
+ "uniform2uiv",
+ "uniform3f",
+ "uniform3fv",
+ "uniform3i",
+ "uniform3iv",
+ "uniform3ui",
+ "uniform3uiv",
+ "uniform4f",
+ "uniform4fv",
+ "uniform4i",
+ "uniform4iv",
+ "uniform4ui",
+ "uniform4uiv",
+ "uniformBlockBinding",
+ "uniformMatrix2fv",
+ "uniformMatrix2x3fv",
+ "uniformMatrix2x4fv",
+ "uniformMatrix3fv",
+ "uniformMatrix3x2fv",
+ "uniformMatrix3x4fv",
+ "uniformMatrix4fv",
+ "uniformMatrix4x2fv",
+ "uniformMatrix4x3fv",
+ "unique",
+ "uniqueID",
+ "uniqueNumber",
+ "unit",
+ "unitType",
+ "units",
+ "unloadEventEnd",
+ "unloadEventStart",
+ "unlock",
+ "unmount",
+ "unobserve",
+ "unpause",
+ "unpauseAnimations",
+ "unreadCount",
+ "unregister",
+ "unregisterContentHandler",
+ "unregisterProtocolHandler",
+ "unscopables",
+ "unselectable",
+ "unshift",
+ "unsubscribe",
+ "unsuspendRedraw",
+ "unsuspendRedrawAll",
+ "unwatch",
+ "unwrapKey",
+ "upDegrees",
+ "upX",
+ "upY",
+ "upZ",
+ "update",
+ "updateCommands",
+ "updateIce",
+ "updateInterval",
+ "updatePlaybackRate",
+ "updateRenderState",
+ "updateSettings",
+ "updateTiming",
+ "updateViaCache",
+ "updateWith",
+ "updated",
+ "updating",
+ "upgrade",
+ "upload",
+ "uploadTotal",
+ "uploaded",
+ "upper",
+ "upperBound",
+ "upperOpen",
+ "uri",
+ "url",
+ "urn",
+ "urns",
+ "usages",
+ "usb",
+ "usbVersionMajor",
+ "usbVersionMinor",
+ "usbVersionSubminor",
+ "useCurrentView",
+ "useMap",
+ "useProgram",
+ "usedSpace",
+ "user-select",
+ "userActivation",
+ "userAgent",
+ "userChoice",
+ "userHandle",
+ "userHint",
+ "userLanguage",
+ "userSelect",
+ "userVisibleOnly",
+ "username",
+ "usernameFragment",
+ "utterance",
+ "uuid",
+ "v8BreakIterator",
+ "vAlign",
+ "vLink",
+ "valid",
+ "validate",
+ "validateProgram",
+ "validationMessage",
+ "validity",
+ "value",
+ "valueAsDate",
+ "valueAsNumber",
+ "valueAsString",
+ "valueInSpecifiedUnits",
+ "valueMissing",
+ "valueOf",
+ "valueText",
+ "valueType",
+ "values",
+ "variable",
+ "variant",
+ "variationSettings",
+ "vector-effect",
+ "vectorEffect",
+ "velocityAngular",
+ "velocityExpansion",
+ "velocityX",
+ "velocityY",
+ "vendor",
+ "vendorId",
+ "vendorSub",
+ "verify",
+ "version",
+ "vertexAttrib1f",
+ "vertexAttrib1fv",
+ "vertexAttrib2f",
+ "vertexAttrib2fv",
+ "vertexAttrib3f",
+ "vertexAttrib3fv",
+ "vertexAttrib4f",
+ "vertexAttrib4fv",
+ "vertexAttribDivisor",
+ "vertexAttribDivisorANGLE",
+ "vertexAttribI4i",
+ "vertexAttribI4iv",
+ "vertexAttribI4ui",
+ "vertexAttribI4uiv",
+ "vertexAttribIPointer",
+ "vertexAttribPointer",
+ "vertical",
+ "vertical-align",
+ "verticalAlign",
+ "verticalOverflow",
+ "vh",
+ "vibrate",
+ "vibrationActuator",
+ "videoBitsPerSecond",
+ "videoHeight",
+ "videoTracks",
+ "videoWidth",
+ "view",
+ "viewBox",
+ "viewBoxString",
+ "viewTarget",
+ "viewTargetString",
+ "viewport",
+ "viewportAnchorX",
+ "viewportAnchorY",
+ "viewportElement",
+ "views",
+ "violatedDirective",
+ "visibility",
+ "visibilityState",
+ "visible",
+ "visualViewport",
+ "vlinkColor",
+ "vmax",
+ "vmin",
+ "voice",
+ "voiceURI",
+ "volume",
+ "vrml",
+ "vspace",
+ "vw",
+ "w",
+ "wait",
+ "waitSync",
+ "waiting",
+ "wake",
+ "wakeLock",
+ "wand",
+ "warn",
+ "wasClean",
+ "wasDiscarded",
+ "watch",
+ "watchAvailability",
+ "watchPosition",
+ "webdriver",
+ "webkitAddKey",
+ "webkitAlignContent",
+ "webkitAlignItems",
+ "webkitAlignSelf",
+ "webkitAnimation",
+ "webkitAnimationDelay",
+ "webkitAnimationDirection",
+ "webkitAnimationDuration",
+ "webkitAnimationFillMode",
+ "webkitAnimationIterationCount",
+ "webkitAnimationName",
+ "webkitAnimationPlayState",
+ "webkitAnimationTimingFunction",
+ "webkitAppearance",
+ "webkitAudioContext",
+ "webkitAudioDecodedByteCount",
+ "webkitAudioPannerNode",
+ "webkitBackfaceVisibility",
+ "webkitBackground",
+ "webkitBackgroundAttachment",
+ "webkitBackgroundClip",
+ "webkitBackgroundColor",
+ "webkitBackgroundImage",
+ "webkitBackgroundOrigin",
+ "webkitBackgroundPosition",
+ "webkitBackgroundPositionX",
+ "webkitBackgroundPositionY",
+ "webkitBackgroundRepeat",
+ "webkitBackgroundSize",
+ "webkitBackingStorePixelRatio",
+ "webkitBorderBottomLeftRadius",
+ "webkitBorderBottomRightRadius",
+ "webkitBorderImage",
+ "webkitBorderImageOutset",
+ "webkitBorderImageRepeat",
+ "webkitBorderImageSlice",
+ "webkitBorderImageSource",
+ "webkitBorderImageWidth",
+ "webkitBorderRadius",
+ "webkitBorderTopLeftRadius",
+ "webkitBorderTopRightRadius",
+ "webkitBoxAlign",
+ "webkitBoxDirection",
+ "webkitBoxFlex",
+ "webkitBoxOrdinalGroup",
+ "webkitBoxOrient",
+ "webkitBoxPack",
+ "webkitBoxShadow",
+ "webkitBoxSizing",
+ "webkitCancelAnimationFrame",
+ "webkitCancelFullScreen",
+ "webkitCancelKeyRequest",
+ "webkitCancelRequestAnimationFrame",
+ "webkitClearResourceTimings",
+ "webkitClosedCaptionsVisible",
+ "webkitConvertPointFromNodeToPage",
+ "webkitConvertPointFromPageToNode",
+ "webkitCreateShadowRoot",
+ "webkitCurrentFullScreenElement",
+ "webkitCurrentPlaybackTargetIsWireless",
+ "webkitDecodedFrameCount",
+ "webkitDirectionInvertedFromDevice",
+ "webkitDisplayingFullscreen",
+ "webkitDroppedFrameCount",
+ "webkitEnterFullScreen",
+ "webkitEnterFullscreen",
+ "webkitEntries",
+ "webkitExitFullScreen",
+ "webkitExitFullscreen",
+ "webkitExitPointerLock",
+ "webkitFilter",
+ "webkitFlex",
+ "webkitFlexBasis",
+ "webkitFlexDirection",
+ "webkitFlexFlow",
+ "webkitFlexGrow",
+ "webkitFlexShrink",
+ "webkitFlexWrap",
+ "webkitFullScreenKeyboardInputAllowed",
+ "webkitFullscreenElement",
+ "webkitFullscreenEnabled",
+ "webkitGenerateKeyRequest",
+ "webkitGetAsEntry",
+ "webkitGetDatabaseNames",
+ "webkitGetEntries",
+ "webkitGetEntriesByName",
+ "webkitGetEntriesByType",
+ "webkitGetFlowByName",
+ "webkitGetGamepads",
+ "webkitGetImageDataHD",
+ "webkitGetNamedFlows",
+ "webkitGetRegionFlowRanges",
+ "webkitGetUserMedia",
+ "webkitHasClosedCaptions",
+ "webkitHidden",
+ "webkitIDBCursor",
+ "webkitIDBDatabase",
+ "webkitIDBDatabaseError",
+ "webkitIDBDatabaseException",
+ "webkitIDBFactory",
+ "webkitIDBIndex",
+ "webkitIDBKeyRange",
+ "webkitIDBObjectStore",
+ "webkitIDBRequest",
+ "webkitIDBTransaction",
+ "webkitImageSmoothingEnabled",
+ "webkitIndexedDB",
+ "webkitInitMessageEvent",
+ "webkitIsFullScreen",
+ "webkitJustifyContent",
+ "webkitKeys",
+ "webkitLineClamp",
+ "webkitLineDashOffset",
+ "webkitLockOrientation",
+ "webkitMask",
+ "webkitMaskClip",
+ "webkitMaskComposite",
+ "webkitMaskImage",
+ "webkitMaskOrigin",
+ "webkitMaskPosition",
+ "webkitMaskPositionX",
+ "webkitMaskPositionY",
+ "webkitMaskRepeat",
+ "webkitMaskSize",
+ "webkitMatchesSelector",
+ "webkitMediaStream",
+ "webkitNotifications",
+ "webkitOfflineAudioContext",
+ "webkitOrder",
+ "webkitOrientation",
+ "webkitPeerConnection00",
+ "webkitPersistentStorage",
+ "webkitPerspective",
+ "webkitPerspectiveOrigin",
+ "webkitPointerLockElement",
+ "webkitPostMessage",
+ "webkitPreservesPitch",
+ "webkitPutImageDataHD",
+ "webkitRTCPeerConnection",
+ "webkitRegionOverset",
+ "webkitRelativePath",
+ "webkitRequestAnimationFrame",
+ "webkitRequestFileSystem",
+ "webkitRequestFullScreen",
+ "webkitRequestFullscreen",
+ "webkitRequestPointerLock",
+ "webkitResolveLocalFileSystemURL",
+ "webkitSetMediaKeys",
+ "webkitSetResourceTimingBufferSize",
+ "webkitShadowRoot",
+ "webkitShowPlaybackTargetPicker",
+ "webkitSlice",
+ "webkitSpeechGrammar",
+ "webkitSpeechGrammarList",
+ "webkitSpeechRecognition",
+ "webkitSpeechRecognitionError",
+ "webkitSpeechRecognitionEvent",
+ "webkitStorageInfo",
+ "webkitSupportsFullscreen",
+ "webkitTemporaryStorage",
+ "webkitTextFillColor",
+ "webkitTextSizeAdjust",
+ "webkitTextStroke",
+ "webkitTextStrokeColor",
+ "webkitTextStrokeWidth",
+ "webkitTransform",
+ "webkitTransformOrigin",
+ "webkitTransformStyle",
+ "webkitTransition",
+ "webkitTransitionDelay",
+ "webkitTransitionDuration",
+ "webkitTransitionProperty",
+ "webkitTransitionTimingFunction",
+ "webkitURL",
+ "webkitUnlockOrientation",
+ "webkitUserSelect",
+ "webkitVideoDecodedByteCount",
+ "webkitVisibilityState",
+ "webkitWirelessVideoPlaybackDisabled",
+ "webkitdirectory",
+ "webkitdropzone",
+ "webstore",
+ "weight",
+ "whatToShow",
+ "wheelDelta",
+ "wheelDeltaX",
+ "wheelDeltaY",
+ "whenDefined",
+ "which",
+ "white-space",
+ "whiteSpace",
+ "wholeText",
+ "widows",
+ "width",
+ "will-change",
+ "willChange",
+ "willValidate",
+ "window",
+ "withCredentials",
+ "word-break",
+ "word-spacing",
+ "word-wrap",
+ "wordBreak",
+ "wordSpacing",
+ "wordWrap",
+ "workerStart",
+ "wrap",
+ "wrapKey",
+ "writable",
+ "writableAuxiliaries",
+ "write",
+ "writeText",
+ "writeValue",
+ "writeWithoutResponse",
+ "writeln",
+ "writing-mode",
+ "writingMode",
+ "x",
+ "x1",
+ "x2",
+ "xChannelSelector",
+ "xmlEncoding",
+ "xmlStandalone",
+ "xmlVersion",
+ "xmlbase",
+ "xmllang",
+ "xmlspace",
+ "xor",
+ "xr",
+ "y",
+ "y1",
+ "y2",
+ "yChannelSelector",
+ "yandex",
+ "z",
+ "z-index",
+ "zIndex",
+ "zoom",
+ "zoomAndPan",
+ "zoomRectScreen",
+ "PropertyKey",
+ "PropertyDescriptor",
+ "configurable",
+ "enumerable",
+ "PropertyDescriptorMap",
+ "ObjectConstructor",
+ "FunctionConstructor",
+ "ThisParameterType",
+ "OmitThisParameter",
+ "CallableFunction",
+ "NewableFunction",
+ "IArguments",
+ "callee",
+ "StringConstructor",
+ "BooleanConstructor",
+ "NumberConstructor",
+ "TemplateStringsArray",
+ "ImportMeta",
+ "DateConstructor",
+ "RegExpMatchArray",
+ "RegExpExecArray",
+ "RegExpConstructor",
+ "ErrorConstructor",
+ "EvalErrorConstructor",
+ "RangeErrorConstructor",
+ "ReferenceErrorConstructor",
+ "SyntaxErrorConstructor",
+ "TypeErrorConstructor",
+ "URIErrorConstructor",
+ "ReadonlyArray",
+ "ConcatArray",
+ "ArrayConstructor",
+ "TypedPropertyDescriptor",
+ "ClassDecorator",
+ "PropertyDecorator",
+ "MethodDecorator",
+ "ParameterDecorator",
+ "PromiseConstructorLike",
+ "PromiseLike",
+ "ArrayLike",
+ "Partial",
+ "Required",
+ "Readonly",
+ "Pick",
+ "Record",
+ "Exclude",
+ "Extract",
+ "Omit",
+ "NonNullable",
+ "Parameters",
+ "ConstructorParameters",
+ "ReturnType",
+ "InstanceType",
+ "Uppercase",
+ "Lowercase",
+ "Capitalize",
+ "Uncapitalize",
+ "ThisType",
+ "ArrayBufferTypes",
+ "ArrayBufferLike",
+ "ArrayBufferConstructor",
+ "ArrayBufferView",
+ "DataViewConstructor",
+ "Int8ArrayConstructor",
+ "Uint8ArrayConstructor",
+ "Uint8ClampedArrayConstructor",
+ "Int16ArrayConstructor",
+ "Uint16ArrayConstructor",
+ "Int32ArrayConstructor",
+ "Uint32ArrayConstructor",
+ "Float32ArrayConstructor",
+ "Float64ArrayConstructor",
+ "CollatorOptions",
+ "usage",
+ "localeMatcher",
+ "numeric",
+ "caseFirst",
+ "sensitivity",
+ "ignorePunctuation",
+ "ResolvedCollatorOptions",
+ "collation",
+ "compare",
+ "resolvedOptions",
+ "supportedLocalesOf",
+ "NumberFormatOptions",
+ "currency",
+ "currencyDisplay",
+ "currencySign",
+ "useGrouping",
+ "minimumIntegerDigits",
+ "minimumFractionDigits",
+ "maximumFractionDigits",
+ "minimumSignificantDigits",
+ "maximumSignificantDigits",
+ "ResolvedNumberFormatOptions",
+ "numberingSystem",
+ "DateTimeFormatOptions",
+ "weekday",
+ "era",
+ "year",
+ "month",
+ "day",
+ "hour",
+ "minute",
+ "second",
+ "timeZoneName",
+ "formatMatcher",
+ "hour12",
+ "timeZone",
+ "ResolvedDateTimeFormatOptions",
+ "calendar"
+]
\ No newline at end of file
diff --git a/arkguard/src/generator/DictionaryNameGenerator.ts b/arkguard/src/generator/DictionaryNameGenerator.ts
new file mode 100644
index 0000000000000000000000000000000000000000..70eb3d9a5cbdb607e22cf606c799916c4e416151
--- /dev/null
+++ b/arkguard/src/generator/DictionaryNameGenerator.ts
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import type {INameGenerator, NameGeneratorOptions} from './INameGenerator';
+
+/**
+ * @Desc: a name generator which use given identifiers to get incremental obfuscated name
+ */
+export class DictionaryNameGenerator implements INameGenerator {
+ private readonly mDictionaryList: string[];
+ private readonly mReservedNames: Set;
+
+ private mDictIndex: number;
+ private mTransformNumber: number;
+
+ /**
+ *
+ * @param options: {dictionaryList: list}
+ */
+ constructor(options?: NameGeneratorOptions) {
+ this.mDictionaryList = (options && options.dictionaryList) ? options.dictionaryList : ['hello', 'world', 'dictionary', 'light', 'thunder', 'storm'];
+ this.mReservedNames = options?.reservedNames;
+
+ this.mDictIndex = 0;
+ this.mTransformNumber = 0;
+ }
+
+ /**
+ * @return: null for end
+ */
+ public getName(): string {
+ if (this.mDictIndex >= this.mDictionaryList.length) {
+ return null;
+ }
+
+ let originIdentifier: string[] = Array.from(this.mDictionaryList[this.mDictIndex].toLowerCase());
+ const BINARY_RADIX: number = 2;
+ let binary: string = this.mTransformNumber.toString(BINARY_RADIX).split('').reverse().join('');
+ let countTrue: number = 0;
+ for (let i = 0; i < binary.length; i++) {
+ if (binary[i] === '1') {
+ originIdentifier[i] = originIdentifier[i].toUpperCase();
+ countTrue += 1;
+ }
+ }
+
+ this.mTransformNumber += 1;
+ if (countTrue >= originIdentifier.length) {
+ this.mDictIndex += 1;
+ this.mTransformNumber = 0;
+ }
+
+ if (this.mReservedNames?.has(originIdentifier.join(''))) {
+ return this.getName();
+ }
+
+ return originIdentifier.join('');
+ }
+
+ public reset(): void {
+ this.mDictIndex = 0;
+ this.mTransformNumber = 0;
+ }
+}
diff --git a/arkguard/src/generator/DisorderNameGenerator.ts b/arkguard/src/generator/DisorderNameGenerator.ts
new file mode 100644
index 0000000000000000000000000000000000000000..30ed891021b54c75fb0491cd3fa198c7b23fa908
--- /dev/null
+++ b/arkguard/src/generator/DisorderNameGenerator.ts
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import type {INameGenerator, NameGeneratorOptions} from './INameGenerator';
+import {ListUtil} from '../utils/ListUtil';
+
+/**
+ * @Desc: simple disordered name generator
+ * e.g.: c, b, z, a, ..., d1, a1, z1, ...
+ */
+export class DisorderNameGenerator implements INameGenerator {
+ private mCharIndex: number;
+ private mLoopNumber: number;
+ private mReservedNames: Set;
+
+ private readonly CHAR_COUNT: number = 26;
+ private readonly CHAR_CODE_A: number = 97;
+
+ private readonly mCharIndexList: number[];
+
+ constructor(options?: NameGeneratorOptions) {
+ this.mCharIndex = 0;
+ this.mLoopNumber = 0;
+ this.mReservedNames = options?.reservedNames;
+
+ this.mCharIndexList = ListUtil.getInitList(this.CHAR_COUNT);
+ ListUtil.shuffle(this.mCharIndexList);
+ }
+
+ private updateElements(): void {
+ this.mCharIndex = (this.mCharIndex + 1) % this.CHAR_COUNT;
+
+ if (this.mCharIndex === 0) {
+ this.mLoopNumber += 1;
+ ListUtil.shuffle(this.mCharIndexList);
+ }
+ }
+
+ public getName(): string {
+ let generatedName: string = String.fromCharCode(this.CHAR_CODE_A + this.mCharIndexList[this.mCharIndex]);
+ if (this.mLoopNumber > 0) {
+ generatedName += this.mLoopNumber;
+ }
+
+ // update elements after generate name
+ this.updateElements();
+ if (this.mReservedNames?.has(generatedName)) {
+ return this.getName();
+ }
+
+ return generatedName;
+ }
+
+ public reset(): void {
+ this.mCharIndex = 0;
+ this.mLoopNumber = 0;
+ ListUtil.shuffle(this.mCharIndexList);
+ }
+}
diff --git a/arkguard/src/generator/HexNameGenerator.ts b/arkguard/src/generator/HexNameGenerator.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3c808e0d6b8e90883ad874f62cd5597ad395b8d4
--- /dev/null
+++ b/arkguard/src/generator/HexNameGenerator.ts
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import {randomBytes} from 'crypto';
+
+import type {INameGenerator, NameGeneratorOptions} from './INameGenerator';
+
+/**
+ * @Desc: a name generator which used given length to generate random length-limiting name
+ */
+export class HexNameGenerator implements INameGenerator {
+ private readonly mHexLength: number;
+ private readonly mReservedNames: Set;
+ private readonly mWithPrefixSuffix: boolean;
+
+ private readonly mHexPrefix: string;
+ private readonly mHexSuffix: string;
+
+ private mHistoryNameList: string[];
+
+ /**
+ * constructor for hex name generator
+ * @param options: {hexLength: number}
+ */
+ constructor(options?: NameGeneratorOptions) {
+ this.mHexLength = 4;
+ if (options && options.hexLength) {
+ this.mHexLength = options.hexLength;
+ }
+
+ this.mWithPrefixSuffix = options && options.hexWithPrefixSuffix;
+ this.mReservedNames = options?.reservedNames;
+
+ this.mHexPrefix = '_0x';
+ this.mHexSuffix = '_';
+
+ this.mHistoryNameList = [];
+ }
+
+ private generateName(): string {
+ let buffer: Buffer = randomBytes(this.mHexLength);
+ let generatedName: string = buffer.toString('hex');
+ if (this.mWithPrefixSuffix) {
+ return this.mHexPrefix + generatedName + this.mHexSuffix;
+ }
+
+ return generatedName;
+ }
+
+ /**
+ * @return: null for end
+ */
+ public getName(): string {
+ while (true) {
+ let generatedName: string = this.generateName();
+ if (!this.mHistoryNameList.includes(generatedName) && !this.mReservedNames?.has(generatedName)) {
+ this.mHistoryNameList.push(generatedName);
+ return generatedName;
+ }
+ const baseHex: number = 16;
+ if (this.mHistoryNameList.length >= Math.pow(baseHex, this.mHexLength)) {
+ return null;
+ }
+ }
+ }
+
+ public reset(): void {
+ this.mHistoryNameList.length = 0;
+ }
+}
diff --git a/arkguard/src/generator/INameGenerator.ts b/arkguard/src/generator/INameGenerator.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ec15117d51ed7c66ab86ff0324e50b32aa05dd39
--- /dev/null
+++ b/arkguard/src/generator/INameGenerator.ts
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+export interface NameGeneratorOptions {
+ // common
+ reservedNames?: Set;
+
+ // hex name generator
+ hexLength?: number;
+ hexWithPrefixSuffix?: boolean;
+
+ // dictionary name generator
+ dictionaryList?: string[];
+
+ // underline name generator
+ underlineMaxLength?: number;
+}
+
+/**
+ * @desc interface for name generator, use factory model
+ */
+export interface INameGenerator {
+ /**
+ * @desc get name from generator.
+ * @return unique name generated
+ */
+ getName(): string;
+
+ /**
+ * @desc reset name generator
+ */
+ reset(): void;
+}
diff --git a/arkguard/src/generator/NameFactory.ts b/arkguard/src/generator/NameFactory.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ee5354a7a116ab17c71f41afe07ac940478183fc
--- /dev/null
+++ b/arkguard/src/generator/NameFactory.ts
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import type {INameGenerator, NameGeneratorOptions} from './INameGenerator';
+import {OrderedNameGenerator} from './OrderedNameGenerator';
+import {DisorderNameGenerator} from './DisorderNameGenerator';
+import {HexNameGenerator} from './HexNameGenerator';
+import {DictionaryNameGenerator} from './DictionaryNameGenerator';
+import {ReservedNameGenerator} from './ReservedNameGenerator';
+import {UnderlineNameGenerator} from './UnderlineNameGenerator';
+
+export enum NameGeneratorType {
+ ORDERED = 1,
+ DISORDERED = 2,
+ HEX = 3,
+ DICTIONARY = 4,
+ RESERVED_NAME = 5,
+ UNDERLINE = 6,
+}
+
+export function getNameGenerator(generatorType: NameGeneratorType, options?: NameGeneratorOptions): INameGenerator {
+ // 10 branch is max in switch
+ switch (generatorType) {
+ case NameGeneratorType.ORDERED:
+ return new OrderedNameGenerator(options);
+ case NameGeneratorType.DISORDERED:
+ return new DisorderNameGenerator(options);
+ case NameGeneratorType.HEX:
+ return new HexNameGenerator(options);
+ case NameGeneratorType.DICTIONARY:
+ return new DictionaryNameGenerator(options);
+ case NameGeneratorType.RESERVED_NAME:
+ return new ReservedNameGenerator(options);
+ case NameGeneratorType.UNDERLINE:
+ return new UnderlineNameGenerator(options);
+ default:
+ console.error('name generator type in getGenerator() is not support');
+ return new OrderedNameGenerator(options);
+ }
+}
diff --git a/arkguard/src/generator/OrderedNameGenerator.ts b/arkguard/src/generator/OrderedNameGenerator.ts
new file mode 100644
index 0000000000000000000000000000000000000000..699db8c1946ec21f6871f5176fe29f89e0755a0b
--- /dev/null
+++ b/arkguard/src/generator/OrderedNameGenerator.ts
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import type {INameGenerator, NameGeneratorOptions} from './INameGenerator';
+
+/**
+ * @desc simple ordered name generator, e.g.: a, b, c, d, ..., a1, b1, c1, ...
+ */
+export class OrderedNameGenerator implements INameGenerator {
+ private mCharIndex: number;
+ private mLoopNumber: number;
+ private mReservedNames: Set;
+
+ private readonly CHAR_COUNT: number = 26;
+ private readonly CHAR_CODE_A: number = 97;
+
+ constructor(options?: NameGeneratorOptions) {
+ this.mCharIndex = 0;
+ this.mLoopNumber = 0;
+ this.mReservedNames = options?.reservedNames;
+ }
+
+ private updateElements(): void {
+ this.mCharIndex = (this.mCharIndex + 1) % this.CHAR_COUNT;
+ if (this.mCharIndex === 0) {
+ this.mLoopNumber += 1;
+ }
+ }
+
+ public getName(): string {
+ let generatedName: string = String.fromCharCode(this.CHAR_CODE_A + this.mCharIndex);
+ if (this.mLoopNumber > 0) {
+ generatedName += this.mLoopNumber;
+ }
+
+ this.updateElements();
+ if (this.mReservedNames?.has(generatedName)) {
+ return this.getName();
+ }
+
+ return generatedName;
+ }
+
+ public reset(): void {
+ this.mCharIndex = 0;
+ this.mLoopNumber = 0;
+ }
+}
diff --git a/arkguard/src/generator/ReservedNameGenerator.ts b/arkguard/src/generator/ReservedNameGenerator.ts
new file mode 100644
index 0000000000000000000000000000000000000000..99df5970e2cfb7d91c60c76c38c64d1d8fd80b3b
--- /dev/null
+++ b/arkguard/src/generator/ReservedNameGenerator.ts
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import type {INameGenerator, NameGeneratorOptions} from './INameGenerator';
+
+/**
+ * need reserved keyword which contain transformDict character
+ */
+const gReservedIdentifier = [
+ 'let', 'return', 'break', 'continue', 'const', 'var', 'console', 'enum',
+ 'boolean', 'number', 'string', 'any', 'void', 'undefined', 'null',
+ 'never', 'function', 'declare', 'as', 'while', 'for', 'if', 'else',
+ 'true', 'false', 'try', 'catch', 'throw', 'type', 'class', 'new',
+ 'interface', 'export', 'readonly', 'private', 'public', 'extends',
+ 'implements', 'constructor', 'this', 'static', 'protected', 'switch',
+ 'case', 'default', 'typeof', 'instanceof', 'in', 'of', 'import', 'require',
+ 'module', 'from', 'abstract', 'async', 'namespace', 'arguments'
+];
+
+const gTransformDict = {
+ 'a': 'α',
+ 'b': 'þ',
+ 'c': 'ç',
+ 'e': 'è',
+ 'i': 'ì',
+ 'k': 'κ',
+ 'l': 'ι',
+ 'n': 'η',
+ 'o': 'ο',
+ 'p': 'ρ',
+ 'u': 'υ',
+ 'v': 'ν',
+ 'w': 'ω',
+ 'x': 'χ',
+ 'y': 'γ',
+ 'z': 'ζ'
+};
+
+/**
+ * @Desc: a name generator which use reserved keywords similar words to get obfuscated name
+ */
+export class ReservedNameGenerator implements INameGenerator {
+ private readonly mReservedNames: Set;
+ private readonly mTransformSet: Set;
+
+ private mIdIndex: number;
+ private readonly mWordInfo: number[];
+ private mWordIndex: number;
+
+ constructor(options?: NameGeneratorOptions) {
+ this.mTransformSet = new Set();
+
+ this.mReservedNames = options?.reservedNames;
+
+ const dictKeys: string[] = Object.keys(gTransformDict);
+ for (const key of dictKeys) {
+ this.mTransformSet.add(key);
+ }
+
+ this.mIdIndex = 0;
+ this.mWordIndex = 1;
+ this.mWordInfo = [];
+
+ this.getWordInfo(gReservedIdentifier[this.mIdIndex]);
+ }
+
+ private getWordInfo(originName: string): void {
+ for (let i = 0; i < originName.length; i++) {
+ if (this.mTransformSet.has(originName[i])) {
+ this.mWordInfo.push(i);
+ }
+ }
+ }
+
+ private transformName(originName: string): string {
+ let charArr: string[] = originName.split('');
+ const BINARY_RADIX: number = 2;
+ let binaryArr: string = this.mWordIndex.toString(BINARY_RADIX).split('').reverse().join('');
+ for (let i = 0; i < binaryArr.length; i++) {
+ if (binaryArr[i] === '1') {
+ charArr[this.mWordInfo[i]] = gTransformDict[charArr[this.mWordInfo[i]]];
+ }
+ }
+
+ this.mWordIndex += 1;
+ if (this.mWordIndex === Math.pow(BINARY_RADIX, this.mWordInfo.length)) {
+ this.mIdIndex += 1;
+ this.mWordInfo.length = 0;
+ this.mWordIndex = 1;
+
+ if (this.mIdIndex < gReservedIdentifier.length) {
+ this.getWordInfo(gReservedIdentifier[this.mIdIndex]);
+ }
+ }
+
+ return charArr.join('');
+ }
+
+ /**
+ * @return: null for end
+ */
+ public getName(): string {
+ let originName: string = gReservedIdentifier[this.mIdIndex];
+
+ let transformedName: string = this.transformName(originName);
+ if (this.mIdIndex >= gReservedIdentifier.length) {
+ return null;
+ }
+
+ if (this.mReservedNames?.has(transformedName)) {
+ return this.getName();
+ }
+
+ return transformedName;
+ }
+
+ public reset(): void {
+ this.mIdIndex = 0;
+ this.mWordIndex = 1;
+ this.mWordInfo.length = 0;
+ this.getWordInfo(gReservedIdentifier[this.mIdIndex]);
+ }
+}
diff --git a/arkguard/src/generator/UnderlineNameGenerator.ts b/arkguard/src/generator/UnderlineNameGenerator.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f10d67d49333da0990840e8e882558184a4e854a
--- /dev/null
+++ b/arkguard/src/generator/UnderlineNameGenerator.ts
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import type {INameGenerator, NameGeneratorOptions} from './INameGenerator';
+
+/**
+ * @Desc: a name generator which use underline to get obfuscated name
+ */
+export class UnderlineNameGenerator implements INameGenerator {
+ private readonly mMaxLength: number;
+ private readonly mReservedNames: Set;
+
+ private mCurrentLength: number;
+
+ constructor(options: NameGeneratorOptions) {
+ const maxValue: number = 128;
+ this.mMaxLength = (options && options.underlineMaxLength) ? options.underlineMaxLength : maxValue;
+ this.mReservedNames = options?.reservedNames;
+ this.mCurrentLength = 1;
+ }
+
+ /**
+ * @return: null for end
+ */
+ public getName(): string {
+ if (this.mCurrentLength > this.mMaxLength) {
+ return null;
+ }
+
+ let targetStr: string = '_'.repeat(this.mCurrentLength);
+ this.mCurrentLength += 1;
+
+ if (this.mReservedNames?.has(targetStr)) {
+ return this.getName();
+ }
+
+ return targetStr;
+ }
+
+ public reset(): void {
+ this.mCurrentLength = 1;
+ }
+}
diff --git a/arkguard/src/transformers/TransformPlugin.ts b/arkguard/src/transformers/TransformPlugin.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f4d43dc606847051d56401be24b55185948aafc9
--- /dev/null
+++ b/arkguard/src/transformers/TransformPlugin.ts
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import type {IOptions} from '../configs/IOptions';
+import type {Node, TransformerFactory} from 'typescript';
+
+export interface TransformPlugin {
+ name: string;
+ order: number
+ createTransformerFactory: (option: IOptions) => TransformerFactory;
+}
diff --git a/arkguard/src/transformers/TransformerManager.ts b/arkguard/src/transformers/TransformerManager.ts
new file mode 100644
index 0000000000000000000000000000000000000000..dee28a04e99eb8c1b31fbe16eba06a99ac023e84
--- /dev/null
+++ b/arkguard/src/transformers/TransformerManager.ts
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import type {Node, TransformerFactory} from 'typescript';
+import {lstatSync, readdirSync} from 'fs';
+import {join, resolve} from 'path';
+
+import type {IOptions} from '../configs/IOptions';
+import type {TransformPlugin} from './TransformPlugin';
+
+export class TransformerManager {
+ private static sInstance: TransformerManager | null = null;
+
+ private static readonly sLoadPath: string = join(__dirname, '../', 'transformers');
+
+ private readonly mTransformers: TransformerFactory[];
+
+ public static getInstance(): TransformerManager {
+ if (!this.sInstance) {
+ this.sInstance = new TransformerManager();
+ }
+
+ return this.sInstance as TransformerManager;
+ }
+
+ private constructor() {
+ this.mTransformers = [];
+ }
+
+ public loadTransformers(options: IOptions): TransformerFactory[] {
+ let subFiles: string[] = readdirSync(TransformerManager.sLoadPath);
+ let plugins: TransformPlugin[] = [];
+ for (const subFile of subFiles) {
+ let subPath: string = resolve(TransformerManager.sLoadPath + '/' + subFile);
+ let isDir: boolean = lstatSync(subPath)?.isDirectory();
+ if (!isDir) {
+ continue;
+ }
+
+ let subDir: string[] = readdirSync(subPath);
+ for (const file of subDir) {
+ if (!file.endsWith('.ts')) {
+ continue;
+ }
+ const fileNameNoSuffix = file.lastIndexOf('.d.ts') > -1 ? file.slice(0, file.lastIndexOf('.d.ts')) : file.slice(0, file.lastIndexOf('.ts'));
+ let path: string = join(subPath, fileNameNoSuffix);
+ let module = require(path);
+ let plugin: TransformPlugin = module?.transformerPlugin;
+ if (plugin) {
+ plugins.push(plugin as TransformPlugin);
+ }
+ }
+ }
+
+ plugins.sort((plugin1: TransformPlugin, plugin2: TransformPlugin) => {
+ return plugin1.order - plugin2.order;
+ });
+
+ plugins.forEach((plugin: TransformPlugin) => {
+ let transformerFactory: TransformerFactory = plugin?.createTransformerFactory(options);
+ let name: string = plugin?.name;
+ if (transformerFactory && name) {
+ this.mTransformers.push(transformerFactory);
+ }
+ });
+
+ return this.mTransformers;
+ }
+}
diff --git a/arkguard/src/transformers/bogus/AbstractBogusControlHelper.ts b/arkguard/src/transformers/bogus/AbstractBogusControlHelper.ts
new file mode 100644
index 0000000000000000000000000000000000000000..768a6bea748ac05e0eb8c24a92f2ffbd87178cbb
--- /dev/null
+++ b/arkguard/src/transformers/bogus/AbstractBogusControlHelper.ts
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import type {Block, Statement} from 'typescript';
+
+export abstract class AbstractBogusControlHelper {
+ protected mOriginalUnits: Statement[];
+ protected mUseOpaquePredicate: boolean;
+
+ protected constructor(units: Statement[], useOpaquePredicate: boolean) {
+ this.mOriginalUnits = units;
+ this.mUseOpaquePredicate = useOpaquePredicate;
+ }
+
+ public abstract getNewBlock(bogusBlock: Block): Block;
+
+ public getBogusStruct(bogusBlock: Block): Block {
+ return this.getNewBlock(bogusBlock);
+ }
+}
diff --git a/arkguard/src/transformers/bogus/BogusControlTransformer.ts b/arkguard/src/transformers/bogus/BogusControlTransformer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c924ecf591bc4b5af0e60fd687f1ddf4c6f2c494
--- /dev/null
+++ b/arkguard/src/transformers/bogus/BogusControlTransformer.ts
@@ -0,0 +1,484 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import * as crypto from 'crypto';
+import {
+ factory,
+ forEachChild,
+ isBinaryExpression,
+ isBlock,
+ isBreakOrContinueStatement,
+ isClassDeclaration,
+ isFunctionDeclaration,
+ isFunctionLike,
+ isIdentifier,
+ isLabeledStatement,
+ isPropertyAccessExpression,
+ isSourceFile,
+ isVariableDeclaration,
+ setParentRecursive,
+ SyntaxKind,
+ visitEachChild
+} from 'typescript';
+
+import type {
+ BinaryExpression,
+ BinaryOperator,
+ Block,
+ Node,
+ PropertyAccessExpression,
+ SourceFile,
+ Statement,
+ TransformationContext,
+ Transformer,
+ TransformerFactory
+} from 'typescript';
+
+import type {TransformPlugin} from '../TransformPlugin';
+import type {IOptions} from '../../configs/IOptions';
+import {BogusBlockType} from '../../configs/IBogusControlFlowOption';
+import type {IBogusControlFlowOption} from '../../configs/IBogusControlFlowOption';
+import {NodeUtils} from '../../utils/NodeUtils';
+import {collectExistNames, isObfsIgnoreNode} from '../../utils/TransformUtil';
+import type {AbstractBogusControlHelper} from './AbstractBogusControlHelper';
+import {SimpleBogusControlHelper} from './SimpleBogusControlHelper';
+import type {INameGenerator, NameGeneratorOptions} from '../../generator/INameGenerator';
+import {getNameGenerator, NameGeneratorType} from '../../generator/NameFactory';
+import type {Hash} from 'crypto';
+
+namespace secharmony {
+ const createBogusControlFactory = function (option: IOptions): TransformerFactory {
+ let profile: IBogusControlFlowOption | undefined = option?.mBogusControlFlow;
+ if (!profile || !profile.mEnable || profile.mThreshold <= 0) {
+ return null;
+ }
+
+ return bogusControlFactory;
+
+ function bogusControlFactory(context: TransformationContext): Transformer {
+ let blockMap: Map = new Map();
+ let blockMapKeys: string[] = [];
+ let bogusType: BogusBlockType = BogusBlockType.CURRENT_BLOCK_DEFORM;
+ let sourceFile: SourceFile;
+ let reservedNames: Set;
+ let nameGenerator: INameGenerator;
+
+ return transformer;
+
+ function transformer(node: Node): Node {
+ if (!isSourceFile(node) || node.fileName.endsWith('.d.ts')) {
+ return node;
+ }
+
+ sourceFile = node;
+
+ // we only do bogus control flow with block
+ if (!hasBlock(node)) {
+ return node;
+ }
+
+ reservedNames = collectExistNames(sourceFile);
+ const options: NameGeneratorOptions = {
+ reservedNames: reservedNames
+ };
+ nameGenerator = getNameGenerator(NameGeneratorType.ORDERED, options);
+
+ // if bogus block get from other block rename, extract all available blocks
+ // javascript support current block deform and other block deform, typescript only
+ // support current block deform.
+ if (profile.mInsertBlockType === BogusBlockType.OTHER_BLOCK_RENAME && node.fileName.endsWith('.js')) {
+ bogusType = BogusBlockType.OTHER_BLOCK_RENAME;
+ getAvailableBlocks(node);
+ for (const key of blockMap.keys()) {
+ blockMapKeys.push(key);
+ }
+ }
+
+ return setParentRecursive(bogusAst(node), true);
+ }
+
+ /**
+ * Block is minimum process unit for us in bogus control flow,
+ * we only inject code in the most inner Block
+ * @param node
+ */
+ function bogusAst(node: Node): Node {
+ if (profile.mSkipLoop && NodeUtils.isLoopStatement(node)) {
+ return node;
+ }
+
+ if (!isSourceFile(node) && isObfsIgnoreNode(node, sourceFile)) {
+ return node;
+ }
+
+ if (!isBlock(node)) {
+ return visitEachChild(node, bogusAst, context);
+ }
+
+ const bogusNode: Block = visitEachChild(node, bogusAst, context);
+ return bogusControlFlow(bogusNode);
+ }
+
+ function bogusControlFlow(node: Block): Block {
+ if (NodeUtils.isContainForbidStringStatement(node) || node.statements.length <= 1) {
+ return node;
+ }
+
+ // judge threshold
+ const randomMaxValue: number = 100;
+ const temp: number = crypto.randomInt(randomMaxValue);
+ if (temp > randomMaxValue * profile.mThreshold) {
+ return node;
+ }
+
+ let helper: AbstractBogusControlHelper = new SimpleBogusControlHelper(
+ [...node.statements],
+ profile.mUseOpaquePredicate,
+ nameGenerator
+ );
+
+ const bogusBlock: Block = getBogusBlock(node, context);
+ return helper.getBogusStruct(bogusBlock);
+ }
+
+ /**
+ * random select other block or deform current block as bogus block
+ */
+ function getBogusBlock(node: Block, context: TransformationContext): Block {
+ if (bogusType === BogusBlockType.CURRENT_BLOCK_DEFORM || blockMapKeys.length <= 1) {
+ return deformBlock(node, context);
+ }
+
+ const randomMaxValue: number = 100;
+ let index: number = crypto.randomInt(randomMaxValue) % blockMapKeys.length;
+ if (getHash(NodeUtils.printNode(node, sourceFile)) === blockMapKeys[index]) {
+ index = (index + 1) % blockMapKeys.length;
+ }
+
+ let bogusBlock: Block = blockMap.get(blockMapKeys[index]);
+ // for randomness
+ const deformedBlock: Block = deformBlock(bogusBlock, context);
+ // rename identifier
+ return renameIdentifier(deformedBlock, context, nameGenerator);
+ }
+
+ /**
+ * get all blocks of current source file
+ * @private
+ */
+ function getAvailableBlocks(node: Node): void {
+ if (!isBlock(node)) {
+ node.forEachChild((child) => {
+ getAvailableBlocks(child);
+ });
+
+ return;
+ }
+
+ // remove special statement
+ let deformedBlock: Block = removeSpecial(node);
+ if (deformedBlock === null) {
+ return;
+ }
+
+ // use printer to print block
+ blockMap.set(getHash(NodeUtils.printNode(node, sourceFile)), deformedBlock);
+ node.forEachChild((child) => {
+ getAvailableBlocks(child);
+ });
+ }
+ }
+ };
+
+ const TRANSFORMER_ORDER: number = 4;
+ export let transformerPlugin: TransformPlugin = {
+ 'name': 'BogusControlTransformer',
+ 'createTransformerFactory': createBogusControlFactory,
+ 'order': (1 << TRANSFORMER_ORDER)
+ };
+
+ const hasBlock = function (node: Node): boolean {
+ let flag: boolean = false;
+ let visit = (inputNode): void => {
+ if (flag) {
+ return;
+ }
+
+ if (isBlock(inputNode)) {
+ flag = true;
+ return;
+ }
+
+ forEachChild(inputNode, visit);
+ };
+
+ visit(node);
+ return flag;
+ };
+
+ /**
+ * deform binary expression, example:
+ * a+b; -> a-b;
+ * a += b; -> a -= b;
+ * @param expression
+ * @private
+ */
+ const deformBinary = function (expression: BinaryExpression): BinaryExpression {
+ const binaryOperators: SyntaxKind[] = [
+ SyntaxKind.PlusToken, SyntaxKind.MinusToken, SyntaxKind.AsteriskToken,
+ SyntaxKind.SlashToken, SyntaxKind.BarToken, SyntaxKind.CaretToken,
+ SyntaxKind.AmpersandToken
+ ];
+
+ const kind: SyntaxKind = expression.operatorToken.kind;
+ // plus need consider string value
+ if (kind === SyntaxKind.PlusToken) {
+ if (isBinaryExpression(expression.left) || isBinaryExpression(expression.right)) {
+ return expression;
+ }
+
+ return factory.createBinaryExpression(
+ factory.createBinaryExpression(
+ {...expression.left},
+ SyntaxKind.PlusToken,
+ {...expression.right}
+ ),
+ SyntaxKind.PlusToken,
+ {...expression.left}
+ );
+ }
+
+ if (kind === SyntaxKind.PlusEqualsToken) {
+ return factory.createBinaryExpression(
+ {...expression.left},
+ SyntaxKind.PlusEqualsToken,
+ factory.createBinaryExpression(
+ {...expression.left},
+ SyntaxKind.PlusToken,
+ {...expression.right}
+ )
+ );
+ }
+
+ let replaceKind: SyntaxKind = undefined;
+ if (kind === SyntaxKind.MinusToken || kind === SyntaxKind.AsteriskToken ||
+ kind === SyntaxKind.SlashToken || kind === SyntaxKind.BarToken ||
+ kind === SyntaxKind.CaretToken || kind === SyntaxKind.AmpersandToken ||
+ kind === SyntaxKind.PercentToken) {
+ const randomMaxValue: number = 100;
+ let index: number = crypto.randomInt(randomMaxValue) % binaryOperators.length;
+ if (binaryOperators[index] === expression.operatorToken.kind) {
+ index = (index + 1) % binaryOperators.length;
+ }
+
+ replaceKind = binaryOperators[index];
+ }
+
+ const binaryEqualOperators: SyntaxKind[] = [SyntaxKind.PlusEqualsToken, SyntaxKind.MinusEqualsToken,
+ SyntaxKind.AsteriskEqualsToken, SyntaxKind.SlashEqualsToken, SyntaxKind.BarEqualsToken,
+ SyntaxKind.CaretEqualsToken, SyntaxKind.AmpersandEqualsToken];
+ if (kind === SyntaxKind.MinusEqualsToken || kind === SyntaxKind.AsteriskEqualsToken ||
+ kind === SyntaxKind.SlashEqualsToken || kind === SyntaxKind.BarEqualsToken ||
+ kind === SyntaxKind.CaretEqualsToken || kind === SyntaxKind.AmpersandEqualsToken) {
+ const randomMaxValue: number = 100;
+ let index: number = crypto.randomInt(randomMaxValue) % binaryEqualOperators.length;
+ if (binaryEqualOperators[index] === expression.operatorToken.kind) {
+ index = (index + 1) % binaryEqualOperators.length;
+ }
+
+ replaceKind = binaryEqualOperators[index];
+ }
+
+ const shiftOperators: SyntaxKind[] = [
+ SyntaxKind.LessThanLessThanToken, SyntaxKind.GreaterThanGreaterThanToken,
+ SyntaxKind.GreaterThanGreaterThanGreaterThanToken
+ ];
+ if (shiftOperators.includes(kind)) {
+ const index: number = (shiftOperators.indexOf(kind) + 1) % shiftOperators.length;
+ replaceKind = shiftOperators[index];
+ }
+
+ const equalOperators: SyntaxKind[] = [
+ SyntaxKind.EqualsEqualsToken, SyntaxKind.ExclamationEqualsToken,
+ SyntaxKind.EqualsEqualsEqualsToken, SyntaxKind.ExclamationEqualsEqualsToken,
+ SyntaxKind.LessThanToken, SyntaxKind.LessThanEqualsToken,
+ SyntaxKind.GreaterThanToken, SyntaxKind.GreaterThanEqualsToken,
+ ];
+ if (equalOperators.includes(kind)) {
+ const index: number = (equalOperators.indexOf(kind) + 1) % equalOperators.length;
+ replaceKind = equalOperators[index];
+ }
+
+ if (replaceKind === undefined) {
+ return expression;
+ }
+
+ return factory.createBinaryExpression(
+ {...expression.left},
+ replaceKind as BinaryOperator,
+ {...expression.right}
+ );
+ };
+
+ /**
+ * find special statement:
+ * return, break, continue, yield, await, super, this
+ * @param statement
+ * @private
+ */
+ const findSpecial = function (statement: Statement): boolean {
+ let result: boolean = false;
+ let visit = (node: Node): void => {
+ if (result) {
+ return;
+ }
+
+ if (isFunctionLike(node) ||
+ NodeUtils.isLoopStatement(node)) {
+ return;
+ }
+
+ if (isBreakOrContinueStatement(node)) {
+ result = true;
+ return;
+ }
+
+ if (node.kind === SyntaxKind.YieldKeyword ||
+ node.kind === SyntaxKind.AwaitKeyword ||
+ node.kind === SyntaxKind.SuperKeyword ||
+ node.kind === SyntaxKind.ThisKeyword) {
+ result = true;
+ return;
+ }
+
+ forEachChild(node, visit);
+ };
+
+ visit(statement);
+ return result;
+ };
+
+ /**
+ * remove special statement of javascript
+ * @param block
+ * @private
+ */
+ const removeSpecial = function (block: Block): Block {
+ const statements: Statement[] = [];
+ for (const statement of block.statements) {
+ if (findSpecial(statement)) {
+ continue;
+ }
+
+ statements.push(statement);
+ }
+
+ if (statements.length === 0) {
+ return null;
+ }
+
+ return factory.createBlock(statements, true);
+ };
+
+ /**
+ * deform block
+ * method:
+ * change binary expression;
+ * change true and false
+ * @private
+ */
+ const deformBlock = function (originBlock: Block, context: TransformationContext): Block {
+ // deform statement
+ function visit(node: Node): Node {
+ switch (node.kind) {
+ case SyntaxKind.PropertyAccessExpression:
+ return NodeUtils.changePropertyAccessToElementAccess(node as PropertyAccessExpression);
+ case SyntaxKind.BinaryExpression:
+ if (NodeUtils.isMostInnerBinary(node)) {
+ return deformBinary(node as BinaryExpression);
+ }
+ break;
+ case SyntaxKind.TrueKeyword:
+ return factory.createFalse();
+ case SyntaxKind.FalseKeyword:
+ return factory.createTrue();
+ case SyntaxKind.ContinueStatement:
+ return factory.createBreakStatement();
+ default:
+ break;
+ }
+
+ return visitEachChild(node, visit, context);
+ }
+
+ return visit(originBlock) as Block;
+ };
+
+ const renameIdentifier = function (originBlock: Block, context: TransformationContext, nameGenerator: INameGenerator): Block {
+ const nameCache: Map = new Map();
+ const labelNameCache: Map = new Map();
+
+ function visit(node: Node): Node {
+ if (!isIdentifier(node) || !node.parent) {
+ return visitEachChild(node, visit, context);
+ }
+
+ if (isLabeledStatement(node.parent)) {
+ const deformedName: string = nameGenerator.getName();
+ labelNameCache.set(node.text, deformedName);
+ return factory.createIdentifier(deformedName);
+ }
+
+ if (isBreakOrContinueStatement(node.parent)) {
+ const foundLabelName: string = labelNameCache.get(node.text);
+ if (foundLabelName) {
+ return factory.createIdentifier(foundLabelName);
+ }
+
+ return node;
+ }
+
+ if (isVariableDeclaration(node.parent) || isFunctionDeclaration(node.parent) || isClassDeclaration(node.parent)) {
+ const deformedName: string = nameGenerator.getName();
+ nameCache.set(node.text, deformedName);
+ return factory.createIdentifier(deformedName);
+ }
+
+ if (isPropertyAccessExpression(node.parent)) {
+ return node;
+ }
+
+ const foundName: string = nameCache.get(node.text);
+ if (foundName) {
+ return factory.createIdentifier(foundName);
+ }
+
+ return node;
+ }
+
+ return visit(originBlock) as Block;
+ };
+
+ /**
+ * get hash value of string
+ * @private
+ */
+ const getHash = function (str: string): string {
+ const hash: Hash = crypto.createHash('sha256');
+ return hash.update(str).digest('hex').toLowerCase();
+ };
+}
+
+export = secharmony;
diff --git a/arkguard/src/transformers/bogus/SimpleBogusControlHelper.ts b/arkguard/src/transformers/bogus/SimpleBogusControlHelper.ts
new file mode 100644
index 0000000000000000000000000000000000000000..53f3bdae6c255bd0d4b7359c4d1a20de36f42192
--- /dev/null
+++ b/arkguard/src/transformers/bogus/SimpleBogusControlHelper.ts
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import {factory, SyntaxKind} from 'typescript';
+import type {BinaryExpression, Block, Expression, IfStatement, Statement} from 'typescript';
+import crypto from 'crypto';
+
+import {AbstractBogusControlHelper} from './AbstractBogusControlHelper';
+import {NodeUtils} from '../../utils/NodeUtils';
+import type {INameGenerator} from '../../generator/INameGenerator';
+
+export class SimpleBogusControlHelper extends AbstractBogusControlHelper {
+ protected mNameGenerator: INameGenerator;
+
+ public constructor(units: Statement[], useOpaquePredicate: boolean, nameGenerator: INameGenerator) {
+ super(units, useOpaquePredicate);
+ this.mNameGenerator = nameGenerator;
+ }
+
+ public getNewBlock(bogusBlock: Block): Block {
+ const preStatements: Statement[] = [];
+ const randomMaxValue: number = 100;
+ const useTrue: boolean = (crypto.randomInt(randomMaxValue) & 1) === 0;
+
+ let predicate: Expression;
+ if (this.mUseOpaquePredicate) {
+ predicate = this.createOpaquePredicate(preStatements, useTrue);
+ } else {
+ predicate = this.createSimplePredicate(preStatements, useTrue);
+ }
+
+ const originalBlock: Block = factory.createBlock([...this.mOriginalUnits], true);
+
+ let ifStatement: IfStatement;
+ if (useTrue) {
+ ifStatement = factory.createIfStatement(predicate, originalBlock, bogusBlock);
+ } else {
+ ifStatement = factory.createIfStatement(predicate, bogusBlock, originalBlock);
+ }
+
+ return factory.createBlock(
+ [
+ ...preStatements,
+ ifStatement
+ ],
+ true
+ );
+ }
+
+ public createSimplePredicate(preStatements: Statement[], useTrue: boolean): Expression {
+ const arrayName: string = this.mNameGenerator.getName();
+ const stringArray: string[] = [];
+ const traversalRange: number = 10;
+ for (let i = 0; i < traversalRange; i++) {
+ stringArray.push(this.mNameGenerator.getName());
+ }
+
+ const arrayInitStatement: Statement = NodeUtils.createArrayInit(true, arrayName,
+ SyntaxKind.StringLiteral, stringArray);
+ preStatements.push(arrayInitStatement);
+
+ const syntaxSymbol: SyntaxKind = useTrue ? SyntaxKind.ExclamationEqualsEqualsToken :
+ SyntaxKind.EqualsEqualsEqualsToken;
+
+ return factory.createBinaryExpression(
+ factory.createElementAccessExpression(
+ factory.createIdentifier(arrayName),
+ factory.createNumericLiteral('1')
+ ),
+ syntaxSymbol,
+ factory.createElementAccessExpression(
+ factory.createIdentifier(arrayName),
+ factory.createNumericLiteral('6')
+ )
+ );
+ }
+
+ /**
+ * create condition judgement use opaque predicate
+ */
+ public createOpaquePredicate(preStatements, useTrue: boolean): Expression {
+ const nameGenerator: INameGenerator = this.mNameGenerator;
+
+ const xName: string = nameGenerator.getName();
+ const randomMaxValue: number = 125;
+ preStatements.push(NodeUtils.createNumericWithRandom(xName, 1, randomMaxValue));
+
+ /**
+ * y < 10 || x * (x + 1) % 2 == 0, always true
+ * x is integer
+ */
+ function method1(): BinaryExpression {
+ const yName: string = nameGenerator.getName();
+ preStatements.push(NodeUtils.createNumericWithRandom(yName, 1, randomMaxValue));
+
+ const left: BinaryExpression = factory.createBinaryExpression(
+ factory.createIdentifier(yName),
+ SyntaxKind.LessThanToken,
+ factory.createNumericLiteral('10')
+ );
+
+ const rightLeft: BinaryExpression = factory.createBinaryExpression(
+ factory.createBinaryExpression(
+ factory.createIdentifier(xName),
+ SyntaxKind.AsteriskToken,
+ factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ factory.createIdentifier(xName),
+ SyntaxKind.PlusToken,
+ factory.createNumericLiteral('1')
+ )
+ )
+ ),
+ SyntaxKind.PercentToken,
+ factory.createNumericLiteral('2')
+ );
+
+ const right: BinaryExpression = factory.createBinaryExpression(
+ rightLeft,
+ SyntaxKind.EqualsEqualsEqualsToken,
+ factory.createNumericLiteral('0')
+ );
+
+ return factory.createBinaryExpression(
+ left,
+ SyntaxKind.BarBarToken,
+ right
+ );
+ }
+
+ /**
+ * 7* x* x − y* y != 1 || y < n, always true
+ * x, y in [0, 125);
+ * n in [0, 125];
+ */
+ function method2(): BinaryExpression {
+ const yName: string = nameGenerator.getName();
+ const randomMaxValue: number = 125;
+ preStatements.push(NodeUtils.createNumericWithRandom(yName, 1, randomMaxValue));
+
+ const nName: string = nameGenerator.getName();
+ preStatements.push(NodeUtils.createNumericWithRandom(nName, 0, randomMaxValue));
+
+ const left: BinaryExpression = factory.createBinaryExpression(
+ factory.createBinaryExpression(
+ factory.createBinaryExpression(
+ factory.createBinaryExpression(
+ factory.createNumericLiteral('7'),
+ SyntaxKind.AsteriskToken,
+ factory.createIdentifier(xName)
+ ),
+ SyntaxKind.AsteriskToken,
+ factory.createIdentifier(xName)
+ ),
+ SyntaxKind.MinusToken,
+ factory.createBinaryExpression(
+ factory.createIdentifier(yName),
+ SyntaxKind.AsteriskToken,
+ factory.createIdentifier(yName)
+ )
+ ),
+ SyntaxKind.ExclamationEqualsEqualsToken,
+ factory.createNumericLiteral('1')
+ );
+
+ const right: BinaryExpression = factory.createBinaryExpression(
+ factory.createIdentifier(yName),
+ SyntaxKind.LessThanToken,
+ factory.createIdentifier(nName)
+ );
+
+ return factory.createBinaryExpression(
+ left,
+ SyntaxKind.BarBarToken,
+ right
+ );
+ }
+
+ /**
+ * (4*x*x + 1) % 19 != 0, always true
+ */
+ function method3(): BinaryExpression {
+ const leftInner: BinaryExpression = factory.createBinaryExpression(
+ factory.createBinaryExpression(
+ factory.createBinaryExpression(
+ factory.createNumericLiteral('4'),
+ SyntaxKind.AsteriskToken,
+ factory.createIdentifier(xName)
+ ),
+ SyntaxKind.AsteriskToken,
+ factory.createIdentifier(xName)
+ ),
+ SyntaxKind.PlusToken,
+ factory.createNumericLiteral('4')
+ );
+
+ const left: BinaryExpression = factory.createBinaryExpression(
+ factory.createParenthesizedExpression(
+ leftInner
+ ),
+ SyntaxKind.PercentToken,
+ factory.createNumericLiteral('19')
+ );
+
+ return factory.createBinaryExpression(
+ left,
+ SyntaxKind.ExclamationEqualsEqualsToken,
+ factory.createNumericLiteral('0')
+ );
+ }
+
+ /**
+ * (x*x + x +7) % 81 != 0, always true
+ */
+ function method4(): BinaryExpression {
+ const leftInner: BinaryExpression = factory.createBinaryExpression(
+ factory.createBinaryExpression(
+ factory.createBinaryExpression(
+ factory.createIdentifier(xName),
+ SyntaxKind.AsteriskToken,
+ factory.createIdentifier(xName)
+ ),
+ SyntaxKind.PlusToken,
+ factory.createIdentifier(xName)
+ ),
+ SyntaxKind.PlusToken,
+ factory.createNumericLiteral('7')
+ );
+
+ const left: BinaryExpression = factory.createBinaryExpression(
+ factory.createParenthesizedExpression(
+ leftInner
+ ),
+ SyntaxKind.PercentToken,
+ factory.createNumericLiteral('81')
+ );
+
+ return factory.createBinaryExpression(
+ left,
+ SyntaxKind.ExclamationEqualsEqualsToken,
+ factory.createNumericLiteral('0')
+ );
+ }
+
+ /**
+ * (x*x*x -x) % 3 == 0, always true
+ */
+ function method5(): BinaryExpression {
+ const leftInner: BinaryExpression = factory.createBinaryExpression(
+ factory.createBinaryExpression(
+ factory.createBinaryExpression(
+ factory.createIdentifier(xName),
+ SyntaxKind.AsteriskToken,
+ factory.createIdentifier(xName)
+ ),
+ SyntaxKind.AsteriskToken,
+ factory.createIdentifier(xName)
+ ),
+ SyntaxKind.MinusToken,
+ factory.createIdentifier(xName)
+ );
+
+ const left: BinaryExpression = factory.createBinaryExpression(
+ factory.createParenthesizedExpression(
+ leftInner
+ ),
+ SyntaxKind.PercentToken,
+ factory.createNumericLiteral('3')
+ );
+
+ return factory.createBinaryExpression(
+ left,
+ SyntaxKind.EqualsEqualsEqualsToken,
+ factory.createNumericLiteral('0')
+ );
+ }
+
+ const methodList: (() => BinaryExpression)[] = [method1, method2, method3, method4, method5];
+ const opaqueMethod: () => BinaryExpression = methodList[crypto.randomInt(methodList.length)];
+
+ if (useTrue) {
+ return opaqueMethod();
+ }
+
+ return factory.createPrefixUnaryExpression(
+ SyntaxKind.ExclamationToken,
+ factory.createParenthesizedExpression(
+ opaqueMethod()
+ )
+ );
+ }
+}
diff --git a/arkguard/src/transformers/control/AbstractControlFlowFlattenHelper.ts b/arkguard/src/transformers/control/AbstractControlFlowFlattenHelper.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c8533b76c0c25fcfe1bd39c78205a8e874d99d10
--- /dev/null
+++ b/arkguard/src/transformers/control/AbstractControlFlowFlattenHelper.ts
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import type {Expression, ForStatement, Statement, SwitchStatement, WhileStatement} from 'typescript';
+
+import type {INameGenerator, NameGeneratorOptions} from '../../generator/INameGenerator';
+import {getNameGenerator, NameGeneratorType} from '../../generator/NameFactory';
+
+export abstract class AbstractControlFlowFlattenHelper {
+ protected mOrderObjName: string;
+
+ protected mIndexName: string;
+
+ protected mOriginalUnits: Statement[];
+
+ protected mStatementUnits: Map;
+
+ protected mNameGenerator: INameGenerator;
+
+ protected constructor(units: Statement[], reservedNames: Set) {
+ this.mOriginalUnits = units;
+ const options: NameGeneratorOptions = {
+ reservedNames: reservedNames
+ };
+ this.mNameGenerator = getNameGenerator(NameGeneratorType.ORDERED, options);
+ this.mOrderObjName = this.mNameGenerator.getName();
+ reservedNames.add(this.mOrderObjName);
+ this.mIndexName = this.mNameGenerator.getName();
+ reservedNames.add(this.mIndexName);
+ }
+
+ public abstract getLoopCondition(): Expression;
+
+ public abstract getLoopStruct(): WhileStatement | ForStatement;
+
+ public abstract getSwitchStruct(): SwitchStatement;
+
+ public abstract getVariableRelatedStatements(): Statement[];
+
+ public getFlattenStruct(): Statement[] {
+ return [...this.getVariableRelatedStatements(), this.getLoopStruct()];
+ }
+}
diff --git a/arkguard/src/transformers/control/ConfusedCharsFlattenHelper.ts b/arkguard/src/transformers/control/ConfusedCharsFlattenHelper.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c608513768ea4053badf8465332654c506c3f2da
--- /dev/null
+++ b/arkguard/src/transformers/control/ConfusedCharsFlattenHelper.ts
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import {
+ factory,
+ isIdentifierStart,
+ isReturnStatement,
+ ScriptTarget,
+ SyntaxKind,
+ NodeFlags
+} from 'typescript';
+
+import type {
+ CaseClause,
+ ObjectLiteralExpression,
+ PropertyAssignment,
+ Statement,
+ SwitchStatement,
+ CallExpression,
+ VariableStatement,
+ ElementAccessExpression
+} from 'typescript';
+
+import {randomInt} from 'crypto';
+
+import {table as confusionTable} from '../../configs/preset/ConfusionTables';
+import {SimpleControlFlowFlattenHelper} from './SimpleControlFlowFlattenHelper';
+
+export class ConfusedCharsFlattenHelper extends SimpleControlFlowFlattenHelper {
+ private readonly mChoiceName: string;
+
+ private mMangledTable: Map;
+
+ private mChooseMaps: Map;
+
+ public constructor(units: Statement[], reservedNames: Set) {
+ super(units, reservedNames);
+
+ this.mChoiceName = this.mNameGenerator.getName();
+ reservedNames.add(this.mChoiceName);
+
+ this.mMangledTable = new Map();
+ this.mChooseMaps = new Map();
+
+ let index: number = 0;
+ const confusionTableKeys: string[] = Object.keys(confusionTable);
+ for (const key of confusionTableKeys) {
+ this.mMangledTable.set(index++, confusionTable[key]);
+ }
+
+ index = 0;
+ let chooseList: string[] = this.chooseMangledChars();
+ for (const [key, _] of this.mStatementUnits) {
+ this.mChooseMaps.set(key, chooseList[index++]);
+ }
+ }
+
+ private chooseMangledChars(): string[] {
+ let chooseList: Set = new Set();
+ let remainLen: number = this.mOriginalUnits.length;
+ let historyIndex: Set = new Set();
+
+ while (remainLen > 0) {
+ if (historyIndex.size === this.mMangledTable.size) {
+ const MIN_UNICODE = 0x100;
+ const MAX_UNICODE = 0x7fff;
+ let unicode: number = randomInt(MIN_UNICODE, MAX_UNICODE);
+ if (isIdentifierStart(unicode, ScriptTarget.ES2015)) {
+ chooseList.add(String.fromCharCode(unicode));
+ remainLen = this.mOriginalUnits.length - chooseList.size;
+ }
+
+ continue;
+ }
+
+ let choice: number = randomInt(0, this.mMangledTable.size);
+ if (historyIndex.has(choice)) {
+ continue;
+ }
+
+ historyIndex.add(choice);
+ let chars: string[] = this.mMangledTable.get(choice).filter((ch) => {
+ return isIdentifierStart(ch.codePointAt(0), ScriptTarget.ES2015);
+ });
+
+ let len: number = chars.length > remainLen ? remainLen : chars.length;
+ chars.slice(0, len).forEach((ch) => {
+ chooseList.add(ch);
+ });
+
+ remainLen = this.mOriginalUnits.length - chooseList.size;
+ }
+
+ return Array.from(chooseList);
+ }
+
+ public getVariableRelatedStatements(): Statement[] {
+ let properties: PropertyAssignment[] = [];
+ this.mChooseMaps.forEach((val, _) => {
+ const RANDOM_MIN = 0;
+ const RANDOM_MAX = 36;
+ const propValue = randomInt(RANDOM_MIN, RANDOM_MAX);
+ let prop: PropertyAssignment = factory.createPropertyAssignment(val, factory.createNumericLiteral(propValue));
+ properties.push(prop);
+ });
+
+ let literal: ObjectLiteralExpression = factory.createObjectLiteralExpression(properties);
+
+ const choiceExpression: CallExpression = factory.createCallExpression(
+ factory.createPropertyAccessExpression(
+ factory.createIdentifier('Object'),
+ factory.createIdentifier('keys')
+ ),
+ undefined,
+ [factory.createIdentifier(this.mOrderObjName)]
+ );
+
+ const variableStatement: VariableStatement = factory.createVariableStatement(
+ undefined,
+ factory.createVariableDeclarationList(
+ [
+ factory.createVariableDeclaration(this.mOrderObjName, undefined, undefined, literal),
+ factory.createVariableDeclaration(this.mIndexName, undefined, undefined, factory.createNumericLiteral(0)),
+ factory.createVariableDeclaration(this.mChoiceName, undefined, undefined, choiceExpression)
+ ],
+ NodeFlags.Let
+ )
+ );
+
+ return [variableStatement];
+ }
+
+ public getSwitchStruct(): SwitchStatement {
+ let condition: ElementAccessExpression = factory.createElementAccessExpression(
+ factory.createIdentifier(this.mChoiceName),
+ factory.createPostfixUnaryExpression(factory.createIdentifier(this.mIndexName), SyntaxKind.PlusPlusToken)
+ );
+
+ let caseList: CaseClause[] = [];
+ for (let index = 0; index < this.mOriginalUnits.length; index++) {
+ let st: Statement = this.mStatementUnits.get(index);
+ let statements: Statement[] = isReturnStatement(st) ? [st] : [st, factory.createContinueStatement()];
+ let caseSt: CaseClause = factory.createCaseClause(
+ factory.createStringLiteral(this.mChooseMaps.get(index)), statements);
+ caseList.push(caseSt);
+ }
+
+ return factory.createSwitchStatement(condition, factory.createCaseBlock(caseList));
+ }
+}
diff --git a/arkguard/src/transformers/control/ControlFlowFlattenTransformer.ts b/arkguard/src/transformers/control/ControlFlowFlattenTransformer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..97728f22adb4b33211d25094294f378c63ba69fa
--- /dev/null
+++ b/arkguard/src/transformers/control/ControlFlowFlattenTransformer.ts
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import {
+ factory,
+ forEachChild,
+ isBlock,
+ isBreakOrContinueStatement, isCallExpression,
+ isClassDeclaration, isExpressionStatement,
+ isFunctionDeclaration,
+ isFunctionLike, isSourceFile, isStringLiteral,
+ isSwitchStatement,
+ isVariableStatement,
+ NodeFlags,
+ setParentRecursive,
+ SyntaxKind,
+ visitEachChild
+} from 'typescript';
+
+import type {
+ Block,
+ Node,
+ SourceFile,
+ Statement,
+ TransformationContext,
+ Transformer,
+ TransformerFactory
+} from 'typescript';
+
+import crypto from 'crypto';
+
+import type {TransformPlugin} from '../TransformPlugin';
+import type {IOptions} from '../../configs/IOptions';
+import type {IControlFlowFatteningOption} from '../../configs/IControlFlowFatteningOption';
+import {SimpleControlFlowFlattenHelper} from './SimpleControlFlowFlattenHelper';
+import {ConfusedCharsFlattenHelper} from './ConfusedCharsFlattenHelper';
+import {NodeUtils} from '../../utils/NodeUtils';
+import {collectExistNames, isObfsIgnoreNode} from '../../utils/TransformUtil';
+
+namespace secharmony {
+
+ const MIN_TARGET_BLOCK_LENGTH: number = 4;
+ const MAX_TARGET_BLOCK_LENGTH: number = 1000;
+
+ const createCfgFlattenFactory = function (option: IOptions): TransformerFactory {
+ let profile: IControlFlowFatteningOption | undefined = option?.mControlFlowFlattening;
+ if (!profile || !profile.mEnable) {
+ return null;
+ }
+
+ return cfgFlattenFactory;
+
+ function cfgFlattenFactory(context: TransformationContext): Transformer {
+ let narrowNames: string[] = option?.mNarrowFunctionNames ?? [];
+ let threshold: number = profile?.mThreshold;
+ let skipLoop: boolean = profile.mSkipLoop;
+ let reservedNames: Set;
+ let sourceFile: SourceFile;
+
+ return controlFlowFlattenTransformer;
+
+ function controlFlowFlattenTransformer(node: Node): Node {
+ if (!isSourceFile(node) || node.fileName.endsWith('.d.ts')) {
+ return node;
+ }
+
+ sourceFile = node;
+ reservedNames = collectExistNames(node);
+
+ return setParentRecursive(controlFlowFlatten(node), true);
+ }
+
+ function controlFlowFlatten(node: Node): Node {
+ if (skipLoop && NodeUtils.isLoopStatement(node)) {
+ return node;
+ }
+
+ if (!isSourceFile(node) && isObfsIgnoreNode(node, sourceFile)) {
+ return node;
+ }
+
+ if (!isBlock(node)) {
+ return visitEachChild(node, controlFlowFlatten, context);
+ }
+
+ let newNode: Block = visitEachChild(node, controlFlowFlatten, context);
+ if (ignoreFlatten(newNode.statements.length) ||
+ NodeUtils.isContainNarrowNames(node, narrowNames)) {
+ return newNode;
+ }
+
+ return factory.createBlock(obfuscateCfg(newNode), true);
+ }
+
+ function obfuscateCfg(node: Block): Statement[] {
+ let finalStatements: Statement[] = [];
+ const continuousStatement: Statement[] = [];
+
+ // 1. filter continuous statements that can be flattened
+ node.statements.forEach((child) => {
+ if (!isForbiddenStatement(child)) {
+ continuousStatement.push(child);
+ return;
+ }
+
+ if (ignoreFlatten(continuousStatement.length)) {
+ finalStatements = [...finalStatements, ...continuousStatement];
+ finalStatements.push(child);
+ continuousStatement.length = 0;
+ return;
+ }
+
+ // 2. flatten continuous statements
+ let helper: SimpleControlFlowFlattenHelper = profile?.mAdvance ?
+ new ConfusedCharsFlattenHelper(continuousStatement, reservedNames) :
+ new SimpleControlFlowFlattenHelper(continuousStatement, reservedNames);
+
+ const flattenStatements: Statement[] = helper.getFlattenStruct();
+ finalStatements = [...finalStatements, ...flattenStatements];
+ finalStatements.push(child);
+ continuousStatement.length = 0;
+ });
+
+ if (ignoreFlatten(continuousStatement.length)) {
+ finalStatements = [...finalStatements, ...continuousStatement];
+ continuousStatement.length = 0;
+ return finalStatements;
+ }
+
+ // 2. flatten continuous statements
+ let finalHelper: SimpleControlFlowFlattenHelper = profile?.mAdvance ?
+ new ConfusedCharsFlattenHelper(continuousStatement, reservedNames) :
+ new SimpleControlFlowFlattenHelper(continuousStatement, reservedNames);
+
+ const flatten: Statement[] = finalHelper.getFlattenStruct();
+ finalStatements = [...finalStatements, ...flatten];
+ return finalStatements;
+ }
+
+ function ignoreFlatten(statementsLen: number): boolean {
+ if (statementsLen < MIN_TARGET_BLOCK_LENGTH || statementsLen > MAX_TARGET_BLOCK_LENGTH) {
+ return true;
+ }
+
+ // judge threshold
+ const randomMaxValue: number = 100;
+ const temp: number = crypto.randomInt(randomMaxValue);
+ return temp > randomMaxValue * threshold;
+ }
+
+ /**
+ * is break or continue statement contained
+ * @param statement
+ */
+ function isContainForbidBreakOrContinue(statement: Statement): boolean {
+ let result: boolean = false;
+ let visit = (n: Node): void => {
+ if (isFunctionLike(n) ||
+ isSwitchStatement(n) ||
+ NodeUtils.isLoopStatement(n)) {
+ return;
+ }
+
+ if (isBreakOrContinueStatement(n)) {
+ result = true;
+ return;
+ }
+
+ forEachChild(n, visit);
+ };
+
+ forEachChild(statement, visit);
+ return result;
+ }
+
+ /**
+ * is statement forbidden in control flow flatten, list of forbidden:
+ * - let/const declaration;
+ * - function declaration;
+ * - class declaration;
+ * - 'use strict' like statement;
+ * - break/continue;
+ * @param statement
+ */
+ function isForbiddenStatement(statement: Statement): boolean {
+ if (isVariableStatement(statement)) {
+ return !!(statement.declarationList.flags & NodeFlags.Const ||
+ statement.declarationList.flags & NodeFlags.Let);
+ }
+
+ if (isExpressionStatement(statement)) {
+ if (isStringLiteral(statement.expression)) {
+ return true;
+ }
+
+ return isCallExpression(statement.expression) &&
+ statement.expression.expression.kind === SyntaxKind.SuperKeyword;
+ }
+
+ return isFunctionDeclaration(statement) ||
+ isClassDeclaration(statement) ||
+ isContainForbidBreakOrContinue(statement);
+ }
+ }
+ };
+
+ const TRANSFORMER_ORDER: number = 7;
+ export let transformerPlugin: TransformPlugin = {
+ 'name': 'ControlFlowFlattenTransformer',
+ 'createTransformerFactory': createCfgFlattenFactory,
+ 'order': (1 << TRANSFORMER_ORDER)
+ };
+}
+
+export = secharmony;
diff --git a/arkguard/src/transformers/control/SimpleControlFlowFlattenHelper.ts b/arkguard/src/transformers/control/SimpleControlFlowFlattenHelper.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0a8eab91e77907cf5df95397e29c5cc5bac1ea09
--- /dev/null
+++ b/arkguard/src/transformers/control/SimpleControlFlowFlattenHelper.ts
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import {
+ factory,
+ isReturnStatement,
+ Map,
+ NodeFlags,
+ SyntaxKind,
+} from 'typescript';
+
+import type {
+ Block,
+ CaseClause,
+ ElementAccessExpression,
+ Expression,
+ ForStatement,
+ NumericLiteral,
+ Statement,
+ SwitchStatement,
+ WhileStatement
+} from 'typescript';
+
+import crypto from 'crypto';
+
+import {AbstractControlFlowFlattenHelper} from './AbstractControlFlowFlattenHelper';
+import {ListUtil} from '../../utils/ListUtil';
+
+export class SimpleControlFlowFlattenHelper extends AbstractControlFlowFlattenHelper {
+ protected mIndexArrayName: string;
+ protected mStringArray: number[];
+ protected mIndexArray: number[];
+
+ public constructor(units: Statement[], reservedNames: Set) {
+ super(units, reservedNames);
+
+ this.mIndexArrayName = this.mNameGenerator.getName();
+ reservedNames.add(this.mIndexArrayName);
+
+ let shuffledArr: number[] = ListUtil.getInitList(units.length);
+ ListUtil.shuffle(shuffledArr);
+
+ this.mStringArray = [...shuffledArr];
+ ListUtil.shuffle(this.mStringArray);
+
+ this.mIndexArray = [];
+ shuffledArr.forEach((value) => {
+ this.mIndexArray.push(this.mStringArray.indexOf(value));
+ });
+
+ this.mStatementUnits = new Map();
+ let index: number = 0;
+ shuffledArr.forEach((val) => {
+ this.mStatementUnits.set(val, this.mOriginalUnits[index++]);
+ });
+ }
+
+ public getSwitchStruct(): SwitchStatement {
+ let condition: ElementAccessExpression = factory.createElementAccessExpression(
+ factory.createIdentifier(this.mOrderObjName),
+ factory.createElementAccessExpression(
+ factory.createIdentifier(this.mIndexArrayName),
+ factory.createPostfixUnaryExpression(
+ factory.createIdentifier(this.mIndexName),
+ SyntaxKind.PlusPlusToken
+ )
+ ));
+
+ let caseList: CaseClause[] = [];
+ for (let index = 0; index < this.mOriginalUnits.length; index++) {
+ let st: Statement = this.mStatementUnits.get(index);
+ let statements: Statement[] = isReturnStatement(st) ? [st] : [st, factory.createContinueStatement()];
+ let caseSt: CaseClause = factory.createCaseClause(
+ factory.createStringLiteral(index.toString()), statements);
+ caseList.push(caseSt);
+ }
+
+ return factory.createSwitchStatement(condition, factory.createCaseBlock(caseList));
+ }
+
+ public getLoopStruct(): WhileStatement | ForStatement {
+ let loopBody: Block = factory.createBlock([
+ this.getSwitchStruct(),
+ factory.createBreakStatement(),
+ ]);
+
+ const MAX_RANDOM = 100;
+ const HALF_RANDOM = 100;
+ const temp: number = crypto.randomInt(MAX_RANDOM);
+ let choice: boolean = temp > HALF_RANDOM;
+ if (choice) {
+ return factory.createForStatement(undefined, undefined, undefined, loopBody);
+ }
+
+ let condition: Expression = this.getLoopCondition();
+ return factory.createWhileStatement(condition, loopBody);
+ }
+
+ public getLoopCondition(): Expression {
+ return factory.createPrefixUnaryExpression(
+ SyntaxKind.ExclamationToken,
+ factory.createPrefixUnaryExpression(
+ SyntaxKind.ExclamationToken,
+ factory.createArrayLiteralExpression([])
+ )
+ );
+ }
+
+ public getVariableRelatedStatements(): Statement[] {
+ let indexStr: string = this.mStringArray.join('|');
+
+ let arrayList: NumericLiteral[] = [];
+ this.mIndexArray.forEach((value) => {
+ arrayList.push(factory.createNumericLiteral(value.toString()));
+ });
+
+ return [
+ factory.createVariableStatement(
+ undefined,
+ factory.createVariableDeclarationList(
+ [
+ factory.createVariableDeclaration(
+ factory.createIdentifier(this.mOrderObjName),
+ undefined,
+ undefined,
+ factory.createCallExpression(
+ factory.createPropertyAccessExpression(
+ factory.createStringLiteral(indexStr),
+ factory.createIdentifier('split')
+ ),
+ undefined,
+ [factory.createStringLiteral('|')]
+ )
+ ),
+ factory.createVariableDeclaration(
+ factory.createIdentifier(this.mIndexArrayName),
+ undefined,
+ undefined,
+ factory.createArrayLiteralExpression(arrayList)
+ ),
+ factory.createVariableDeclaration(
+ factory.createIdentifier(this.mIndexName),
+ undefined,
+ undefined,
+ factory.createNumericLiteral(0)
+ )
+ ],
+ NodeFlags.Let
+ )
+ )
+ ];
+ }
+}
diff --git a/arkguard/src/transformers/data/BoolObfuscationHelper.ts b/arkguard/src/transformers/data/BoolObfuscationHelper.ts
new file mode 100644
index 0000000000000000000000000000000000000000..06fc296eb9babda275666f3b9b52d1da97cd8a3a
--- /dev/null
+++ b/arkguard/src/transformers/data/BoolObfuscationHelper.ts
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import {factory, SyntaxKind} from 'typescript';
+import type {Expression, Node} from 'typescript';
+
+export class BoolObfuscationHelper {
+ public static isBooleanLiteral(node: Node): boolean {
+ return node.kind === SyntaxKind.TrueKeyword || node.kind === SyntaxKind.FalseKeyword;
+ }
+
+ public static isTrueKeyword(node: Node): boolean {
+ return node.kind === SyntaxKind.TrueKeyword;
+ }
+
+ public static createTrueObfuscation(): Expression {
+ return factory.createPrefixUnaryExpression(
+ SyntaxKind.ExclamationToken,
+ factory.createPrefixUnaryExpression(
+ SyntaxKind.ExclamationToken,
+ factory.createArrayLiteralExpression()
+ )
+ );
+ }
+
+ public static createFalseObfuscation(): Expression {
+ return factory.createPrefixUnaryExpression(
+ SyntaxKind.ExclamationToken,
+ factory.createArrayLiteralExpression()
+ );
+ }
+}
diff --git a/arkguard/src/transformers/data/DataObfuscationTransformer.ts b/arkguard/src/transformers/data/DataObfuscationTransformer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9393ab6ba36551e49c97dc8e92a8ef07b9a7462d
--- /dev/null
+++ b/arkguard/src/transformers/data/DataObfuscationTransformer.ts
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import {
+ factory, isElementAccessExpression,
+ isEnumDeclaration, isExportDeclaration,
+ isExpressionStatement, isImportDeclaration,
+ isImportEqualsDeclaration,
+ isSourceFile,
+ isStringLiteralLike, isTypeAliasDeclaration,
+ setParentRecursive,
+ visitEachChild,
+} from 'typescript';
+
+import type {
+ Node,
+ SourceFile,
+ Statement,
+ TransformationContext,
+ Transformer,
+ TransformerFactory
+} from 'typescript';
+
+import crypto from 'crypto';
+
+import type {
+ IBooleanOption,
+ IDataObfuscationOption,
+ INumberOption,
+ IStringOption
+} from '../../configs/IDataObfuscationOption';
+
+import type {TransformPlugin} from '../TransformPlugin';
+import type {IOptions} from '../../configs/IOptions';
+import {SimpleStringObfuscateHelper} from './SimpleStringObfuscateHelper';
+import {NodeUtils} from '../../utils/NodeUtils';
+import type {INameGenerator, NameGeneratorOptions} from '../../generator/INameGenerator';
+import {collectExistNames, isObfsIgnoreNode} from '../../utils/TransformUtil';
+import {getNameGenerator, NameGeneratorType} from '../../generator/NameFactory';
+import {BoolObfuscationHelper} from './BoolObfuscationHelper';
+import {NumberObfuscationHelper} from './NumberObfuscationHelper';
+
+/**
+ * Data obfuscation must follow attribute name obfuscation. Because if data is obfuscated and strings are
+ * extracted onto arrays, attribute name obfuscation may result in some strings not being obfuscated.
+ */
+namespace secharmony {
+ const RANDOM_MAX: number = 100;
+
+ const createDataObfuscationFactory = function (options: IOptions): TransformerFactory {
+ let profile: IDataObfuscationOption | undefined = options?.mDataObfuscation;
+ if (!profile || !profile.mEnable) {
+ return null;
+ }
+
+ return dataObfuscationFactory;
+
+ function dataObfuscationFactory(context: TransformationContext): Transformer {
+ let boolOption: IBooleanOption = profile.mBooleanOption;
+ let stringOption: IStringOption = profile.mStringOption;
+ let numberOption: INumberOption = profile.mNumberOption;
+ let nameGenerator: INameGenerator;
+ let sourceFile: SourceFile;
+
+ return transformer;
+
+ function transformer(node: Node): Node {
+ if (!isSourceFile(node) || node.fileName.endsWith('.d.ts')) {
+ return node;
+ }
+
+ sourceFile = node;
+ let newNode: SourceFile = node;
+
+ if (boolOption && boolOption.mEnable) {
+ newNode = doBoolTransform(newNode) as SourceFile;
+ }
+
+ if (numberOption && numberOption.mEnable) {
+ newNode = doNumberTransform(newNode) as SourceFile;
+ }
+
+ if (stringOption && stringOption.mEnable) {
+ const reservedNames: Set = collectExistNames(node);
+ const generatorOptions: NameGeneratorOptions = {
+ reservedNames: reservedNames
+ };
+
+ nameGenerator = getNameGenerator(NameGeneratorType.ORDERED, generatorOptions);
+ newNode = doStringTransform(newNode, nameGenerator);
+ }
+
+ return newNode;
+ }
+
+ function doBoolTransform(node: Node): Node {
+ if (boolOption.mSkipLoop && NodeUtils.isLoopStatement(node)) {
+ return node;
+ }
+
+ if (!BoolObfuscationHelper.isBooleanLiteral(node)) {
+ return visitEachChild(node, doBoolTransform, context);
+ }
+
+ // threshold check
+ const temp: number = crypto.randomInt(RANDOM_MAX);
+ if (temp > RANDOM_MAX * boolOption.mThreshold) {
+ return node;
+ }
+
+ if (BoolObfuscationHelper.isTrueKeyword(node)) {
+ return BoolObfuscationHelper.createTrueObfuscation();
+ }
+
+ return BoolObfuscationHelper.createFalseObfuscation();
+ }
+
+ function doNumberTransform(node: Node): Node {
+ if (numberOption.mSkipLoop && NodeUtils.isLoopStatement(node)) {
+ return node;
+ }
+
+ if (!NumberObfuscationHelper.isTargetNumberNode(node)) {
+ return visitEachChild(node, doNumberTransform, context);
+ }
+
+ // threshold check
+ const temp: number = crypto.randomInt(RANDOM_MAX);
+ if (temp > RANDOM_MAX * numberOption.mThreshold) {
+ return node;
+ }
+
+ return NumberObfuscationHelper.convertNumberToExpression(node);
+ }
+
+ function doStringTransform(node: SourceFile, generator: INameGenerator): SourceFile {
+ let helper: SimpleStringObfuscateHelper = new SimpleStringObfuscateHelper(stringOption, generator);
+ helper.collectLiterals(node);
+
+ sourceFile = node as SourceFile;
+ let source: Node = stringVisitor(node);
+ let newStatements: Statement[] = NodeUtils.randomInsertStatements(
+ NodeUtils.randomInsertStatements([...(source as SourceFile).statements],
+ helper.prepareIndexFunctionStruct()),
+ helper.prepareArrayFunctionStruct());
+
+ return setParentRecursive(factory.updateSourceFile(source as SourceFile, newStatements), true);
+
+ function stringVisitor(node: Node): Node {
+ if (stringOption.mSkipLoop && NodeUtils.isLoopStatement(node)) {
+ return node;
+ }
+
+ if (!isSourceFile(node) && isObfsIgnoreNode(node, sourceFile)) {
+ return node;
+ }
+
+ // module name in import / export like statement
+ if ((isImportDeclaration(node) || isExportDeclaration(node)) && node.moduleSpecifier) {
+ return node;
+ }
+
+ if (isImportEqualsDeclaration(node)) {
+ return node;
+ }
+
+ if (isTypeAliasDeclaration(node)) {
+ return node;
+ }
+
+ // TS18033: Only numeric enums can have computed members, but this expression has type 'string'. If
+ // you do not need exhaustiveness checks, consider using an object literal instead.
+ if (isEnumDeclaration(node)) {
+ return node;
+ }
+
+ if (!isStringLiteralLike(node)) {
+ return visitEachChild(node, stringVisitor, context);
+ }
+
+ if (isExpressionStatement(node.parent)) {
+ return node;
+ }
+
+ if (stringOption.mSkipProperty && isElementAccessExpression(node.parent)) {
+ return node;
+ }
+
+ if (stringOption.mReservedStrings && stringOption.mReservedStrings.includes(node.text)) {
+ return node;
+ }
+
+ if (!helper.isTargetStr(node.text)) {
+ return node;
+ }
+
+ if (!NodeUtils.isExtractableString(node)) {
+ return visitEachChild(node, stringVisitor, context);
+ }
+
+ let prob: number = Math.random();
+ if (prob > stringOption.mThreshold) {
+ return node;
+ }
+
+ return helper.prepareReplaceStruct(node);
+ }
+ }
+ }
+ };
+
+ const TRANSFORMER_ORDER: number = 8;
+ export let transformerPlugin: TransformPlugin = {
+ 'name': 'Data Obfuscation',
+ 'order': (1 << TRANSFORMER_ORDER),
+ 'createTransformerFactory': createDataObfuscationFactory
+ };
+}
+
+export = secharmony;
diff --git a/arkguard/src/transformers/data/NumberObfuscationHelper.ts b/arkguard/src/transformers/data/NumberObfuscationHelper.ts
new file mode 100644
index 0000000000000000000000000000000000000000..33063625ce74858cf236ba9984d83f9ad92edfe3
--- /dev/null
+++ b/arkguard/src/transformers/data/NumberObfuscationHelper.ts
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import {factory, isNumericLiteral, isPropertyAssignment, SyntaxKind} from 'typescript';
+import type {BinaryExpression, Node} from 'typescript';
+import {randomInt} from 'crypto';
+
+export class NumberObfuscationHelper {
+ /**
+ * ignore number like property in object
+ * let xxx = {
+ * 0: 13-1,
+ * 1: 1212,
+ * }
+ *
+ * @param node
+ */
+ public static isTargetNumberNode(node: Node): boolean {
+ if (!isNumericLiteral(node)) {
+ return false;
+ }
+
+ if (node.parent && isPropertyAssignment(node.parent)) {
+ return node.parent.name !== node;
+ }
+
+ return true;
+ }
+
+ public static convertNumberToExpression(node: Node): Node {
+ if (!isNumericLiteral(node)) {
+ return node;
+ }
+
+ const originNumber: number = Number(node.text);
+ if (this.isUnsafeNumber(originNumber)) {
+ return node;
+ }
+
+ const [intPart, decimalPart] = this.extractIntegerAndDecimalParts(originNumber);
+
+ // split intPart
+ const MIN_RANDOM = 0xff;
+ const MAX_RIGHT_RANDOM = 0x1fff;
+ const randomLeft: number = randomInt(MIN_RANDOM, MAX_RIGHT_RANDOM);
+ const randomRight: number = intPart - randomLeft;
+
+ const MAX_LEFT_LEFT_RANDOM = 0xfff;
+ const randomLeftLeft: number = randomInt(MIN_RANDOM, MAX_LEFT_LEFT_RANDOM);
+ const randomLeftRight: number = randomLeft - randomLeftLeft;
+
+ const leftPartExpression: BinaryExpression = factory.createBinaryExpression(
+ factory.createBinaryExpression(
+ factory.createNumericLiteral(this.toHexString(randomLeftLeft)),
+ SyntaxKind.BarToken,
+ factory.createNumericLiteral(this.toHexString(randomLeftRight))
+ ),
+ SyntaxKind.PlusToken,
+ factory.createBinaryExpression(
+ factory.createNumericLiteral(this.toHexString(randomLeftLeft)),
+ SyntaxKind.AmpersandToken,
+ factory.createNumericLiteral(this.toHexString(randomLeftRight))
+ )
+ );
+
+ const intPartExpression: BinaryExpression = factory.createBinaryExpression(
+ leftPartExpression,
+ SyntaxKind.PlusToken,
+ factory.createNumericLiteral(this.toHexString(randomRight))
+ );
+
+ if (decimalPart) {
+ return factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ intPartExpression,
+ SyntaxKind.PlusToken,
+ factory.createNumericLiteral(decimalPart)
+ ));
+ }
+
+ return factory.createParenthesizedExpression(intPartExpression);
+ }
+
+ public static extractIntegerAndDecimalParts(number: number): [number, number | null] {
+ const integerPart: number = Math.trunc(number);
+ const decimalPart: number | null = number !== integerPart ? number % 1 : null;
+
+ return [integerPart, decimalPart];
+ }
+
+ public static isUnsafeNumber(number: number): boolean {
+ if (isNaN(number)) {
+ return true;
+ }
+
+ return number < Number.MIN_SAFE_INTEGER || number > Number.MAX_SAFE_INTEGER;
+ }
+
+ public static toHexString(value: number): string {
+ const HEX_RADIX = 16;
+ if (value > 0) {
+ return '0x' + value.toString(HEX_RADIX);
+ }
+
+ const absValue: number = Math.abs(value);
+ return '-0x' + absValue.toString(HEX_RADIX);
+ }
+}
diff --git a/arkguard/src/transformers/data/SimpleStringObfuscateHelper.ts b/arkguard/src/transformers/data/SimpleStringObfuscateHelper.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e4eda5c80216206b4b474319540cd88858109159
--- /dev/null
+++ b/arkguard/src/transformers/data/SimpleStringObfuscateHelper.ts
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import {
+ factory,
+ forEachChild,
+ isStringLiteralLike,
+ NodeFlags,
+} from 'typescript';
+
+import type {
+ CallExpression,
+ Expression,
+ FunctionDeclaration,
+ Node,
+ ParameterDeclaration,
+ ReturnStatement,
+ SourceFile, Statement,
+ StringLiteralLike,
+ VariableDeclaration,
+ VariableStatement
+} from 'typescript';
+
+import {createStringUnit, EncryptType} from './StringUnit';
+import type {StringUnit} from './StringUnit';
+import type {IStringOption} from '../../configs/IDataObfuscationOption';
+import {Base64Helper} from '../../utils/EncryptedUtils';
+import {NodeUtils} from '../../utils/NodeUtils';
+import type {INameGenerator} from '../../generator/INameGenerator';
+
+export class SimpleStringObfuscateHelper {
+ private stringUnits: Map;
+
+ private stringArray: string[];
+
+ private profile: IStringOption;
+
+ private readonly arrayFuncName: string;
+
+ private readonly indexFuncName: string;
+
+ private readonly mNameGenerator: INameGenerator;
+
+ public constructor(option: IStringOption, generator: INameGenerator) {
+ this.profile = option;
+ this.stringUnits = new Map();
+ this.stringArray = [];
+ this.mNameGenerator = generator;
+ this.arrayFuncName = this.mNameGenerator.getName();
+ this.indexFuncName = this.mNameGenerator.getName();
+ }
+
+ public collectLiterals(sourceFile: SourceFile): void {
+ let visit = (node: Node): void => {
+ if (!isStringLiteralLike(node)) {
+ forEachChild(node, visit);
+ return;
+ }
+
+ // filter octal encode string
+ let code: string = NodeUtils.printNode(node, sourceFile);
+ const MIN_OCTAL_LEN: number = 3;
+ const ZERO_INDEX = 2;
+ if (code.length >= MIN_OCTAL_LEN && code[1].startsWith('\\') && code[ZERO_INDEX].startsWith('0')) {
+ return;
+ }
+
+ // extract all
+ let content: string = node.text;
+ if (!content) {
+ return;
+ }
+
+ if (this.stringUnits.has(content)) {
+ let unit: StringUnit = this.stringUnits.get(content);
+ unit.nodeList.push(node);
+ } else {
+ let unit: StringUnit = createStringUnit(node);
+ if (this.profile.mEncryptType === EncryptType.BASE64) {
+ let encrypted: string = new Base64Helper().encode(content);
+ if (encrypted) {
+ unit.encryptContent = encrypted;
+ } else {
+ return;
+ }
+ }
+
+ this.stringArray.push(unit.encryptContent);
+ this.stringUnits.set(content, unit);
+ }
+
+ forEachChild(node, visit);
+ };
+
+ visit(sourceFile);
+ }
+
+ public prepareReplaceStruct(literal: StringLiteralLike): Node {
+ let stringUnit: StringUnit = this.stringUnits.get(literal.text);
+ if (!stringUnit) {
+ return literal;
+ }
+
+ let index: number = this.stringArray.indexOf(stringUnit.encryptContent);
+ if (index < 0) {
+ return literal;
+ }
+
+ return factory.createCallExpression(
+ factory.createIdentifier(this.indexFuncName),
+ undefined,
+ [factory.createNumericLiteral(index)]
+ );
+ }
+
+ public prepareArrayFunctionStruct(): FunctionDeclaration {
+ let statements: Statement[] = [];
+
+ // string nodes in array
+ let arrNodes: Expression[] = [];
+ this.stringArray.forEach((element) => {
+ arrNodes.push(factory.createStringLiteral(element));
+ });
+
+ let arrName: string = this.mNameGenerator.getName();
+ let arrStruct: VariableDeclaration = factory.createVariableDeclaration(
+ factory.createIdentifier(arrName),
+ undefined,
+ undefined,
+ factory.createArrayLiteralExpression(
+ arrNodes,
+ true
+ )
+ );
+
+ let arrFuncStruct: VariableDeclaration = factory.createVariableDeclaration(
+ factory.createIdentifier(this.arrayFuncName),
+ undefined,
+ undefined,
+ factory.createFunctionExpression(
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ [],
+ undefined,
+ factory.createBlock(
+ [factory.createReturnStatement(factory.createIdentifier(arrName))],
+ true
+ )
+ )
+ );
+
+ let declarationStatement: VariableStatement = factory.createVariableStatement(undefined,
+ factory.createVariableDeclarationList([arrStruct, arrFuncStruct], NodeFlags.Const));
+ statements.push(declarationStatement);
+
+ let callExpr: CallExpression = factory.createCallExpression(
+ factory.createIdentifier(this.arrayFuncName),
+ undefined,
+ []
+ );
+
+ let returnStatement: ReturnStatement = factory.createReturnStatement(callExpr);
+ statements.push(returnStatement);
+
+ return factory.createFunctionDeclaration(
+ undefined,
+ undefined,
+ undefined,
+ factory.createIdentifier(this.arrayFuncName),
+ undefined,
+ [],
+ undefined,
+ factory.createBlock(statements, true)
+ );
+ }
+
+ public prepareIndexFunctionStruct(): FunctionDeclaration {
+ let statements: Statement[] = [];
+ let indexName: string = this.mNameGenerator.getName();
+ let arrName: string = this.mNameGenerator.getName();
+
+ let arrStruct: VariableDeclaration = factory.createVariableDeclaration(
+ factory.createIdentifier(arrName),
+ undefined,
+ undefined,
+ factory.createCallExpression(
+ factory.createIdentifier(this.arrayFuncName),
+ undefined,
+ []
+ ));
+
+ let indexFuncStruct: VariableDeclaration = factory.createVariableDeclaration(
+ factory.createIdentifier(this.indexFuncName),
+ undefined,
+ undefined,
+ factory.createFunctionExpression(
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ [factory.createParameterDeclaration(
+ undefined,
+ undefined,
+ undefined,
+ factory.createIdentifier(indexName),
+ undefined,
+ undefined,
+ undefined,
+ )],
+ undefined,
+ factory.createBlock(
+ [
+ factory.createReturnStatement(factory.createElementAccessExpression(
+ factory.createIdentifier(arrName),
+ factory.createIdentifier(indexName),
+ ))
+ ]
+ )
+ )
+ );
+
+ let declaration: VariableStatement = factory.createVariableStatement(
+ undefined,
+ factory.createVariableDeclarationList(
+ [
+ arrStruct,
+ indexFuncStruct,
+ ],
+ NodeFlags.Const
+ ));
+ statements.push(declaration);
+
+ let callExpr: CallExpression = factory.createCallExpression(
+ factory.createIdentifier(this.indexFuncName),
+ undefined,
+ [factory.createIdentifier(indexName)]);
+
+ if (this.profile.mEncryptType === EncryptType.BASE64) {
+ let decryptName: string = this.mNameGenerator.getName();
+ let decryptStruct: Statement = this.prepareDecryptFuncStruct(decryptName);
+ statements.push(decryptStruct);
+ callExpr = factory.createCallExpression(factory.createIdentifier(decryptName), undefined, [callExpr]);
+ }
+
+ let returnStatement: ReturnStatement = factory.createReturnStatement(callExpr);
+ statements.push(returnStatement);
+
+ let paramStruct: ParameterDeclaration = factory.createParameterDeclaration(
+ undefined,
+ undefined,
+ undefined,
+ factory.createIdentifier(indexName),
+ undefined,
+ undefined,
+ undefined
+ );
+
+ return factory.createFunctionDeclaration(
+ undefined,
+ undefined,
+ undefined,
+ factory.createIdentifier(this.indexFuncName),
+ undefined,
+ [paramStruct],
+ undefined,
+ factory.createBlock(statements, true));
+ }
+
+ public isTargetStr(str: string): boolean {
+ return this.stringUnits.has(str);
+ }
+
+ public prepareDecryptFuncStruct(name: string): Statement {
+ let names: string[] = [];
+
+ names.push(name);
+ names.push(this.mNameGenerator.getName());
+ names.push(this.mNameGenerator.getName());
+ names.push(this.mNameGenerator.getName());
+ names.push(this.mNameGenerator.getName());
+ names.push(this.mNameGenerator.getName());
+ names.push(this.mNameGenerator.getName());
+ names.push(this.mNameGenerator.getName());
+ names.push(this.mNameGenerator.getName());
+
+ return new Base64Helper().decodeStruct(names);
+ }
+}
diff --git a/arkguard/src/transformers/data/StringUnit.ts b/arkguard/src/transformers/data/StringUnit.ts
new file mode 100644
index 0000000000000000000000000000000000000000..45999ae1cdfd7d5d1ee7a2552774797ce99dbd6f
--- /dev/null
+++ b/arkguard/src/transformers/data/StringUnit.ts
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import type {Node, StringLiteralLike} from 'typescript';
+
+export enum EncryptType {
+ NONE = 0,
+ BASE64 = 1,
+ RC4 = 2,
+ AES256 = 3,
+}
+
+export interface StringUnit {
+ // content of a string unit
+ 'content': string,
+ // order of string in array
+ 'order': number;
+ // related node list of current string unit
+ 'nodeList': Node[];
+ // encrypt algorithm for string
+ 'encryptAlgo': EncryptType;
+ // content after encryption.
+ 'encryptContent': string;
+}
+
+export function createStringUnit(node: StringLiteralLike, index: number = -1): StringUnit {
+ return {
+ content: node.text,
+ order: index,
+ nodeList: [node],
+ encryptAlgo: EncryptType.NONE,
+ encryptContent: node.text,
+ };
+}
diff --git a/arkguard/src/transformers/instruction/InstructionObfsHelper.ts b/arkguard/src/transformers/instruction/InstructionObfsHelper.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8a01e81b002e1014b67e87e71d21bf369f022c58
--- /dev/null
+++ b/arkguard/src/transformers/instruction/InstructionObfsHelper.ts
@@ -0,0 +1,678 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import {
+ factory,
+ NodeFlags,
+ SyntaxKind,
+} from 'typescript';
+
+import type {
+ BinaryExpression,
+ Block,
+ CallExpression,
+ Expression,
+ FunctionExpression,
+ Identifier,
+ ObjectLiteralExpression,
+ ParameterDeclaration,
+ ParenthesizedExpression,
+ PropertyAssignment,
+ VariableStatement
+} from 'typescript';
+
+import * as crypto from 'crypto';
+import type {INameGenerator} from '../../generator/INameGenerator';
+import {NodeUtils} from '../../utils/NodeUtils';
+
+export class InstructionHelper {
+ private readonly mArgcFuncMap: Map;
+ private readonly mReservedIdentifiers: Set;
+ private readonly mNameGenerator: INameGenerator;
+
+ constructor(nameGenerator: INameGenerator) {
+ this.mArgcFuncMap = new Map();
+ this.mReservedIdentifiers = new Set();
+ this.mNameGenerator = nameGenerator;
+ }
+
+ /**
+ * ignore deform for special function call
+ * @param callExpression
+ * @private
+ */
+ private isSpecialFunctionCall(callExpression: CallExpression): boolean {
+ return callExpression.expression.kind === SyntaxKind.SuperKeyword;
+ }
+
+ /**
+ * deform call expression, only support function of identifier expression
+ * @param callExpression
+ * @param varName
+ * @param pairArray
+ */
+ public deformCallExpression(callExpression: CallExpression, varName: string, pairArray: PropertyAssignment[]): CallExpression {
+ if (this.isSpecialFunctionCall(callExpression)) {
+ return callExpression;
+ }
+
+ // parse the information in the original instruction: function name, parameter list, and number of parameters
+ const argsCount: number = callExpression.arguments.length;
+
+ for (const arg of callExpression.arguments) {
+ if (arg.kind === SyntaxKind.Identifier) {
+ this.mReservedIdentifiers.add((arg as Identifier).text);
+ }
+ }
+
+ const funcName: Expression = {...callExpression.expression};
+
+ // if there is no deformation function corresponding to the number of parameters,
+ // generate a new pair, add it to the pairArray, and update the argcMap
+ if (this.mArgcFuncMap.get(argsCount) === undefined) {
+ const newPair: PropertyAssignment = this.createPair(argsCount);
+ pairArray.push(newPair);
+ }
+
+ // query the corresponding deformation function name in argcMap and deform callExpression
+ return factory.createCallExpression(
+ factory.createElementAccessExpression(
+ factory.createIdentifier(varName),
+ factory.createStringLiteral(this.mArgcFuncMap.get(argsCount))
+ ),
+ undefined,
+ [
+ funcName,
+ ...callExpression.arguments
+ ]
+ );
+ }
+
+ public getReservedIdentifiers(): Set {
+ return this.mReservedIdentifiers;
+ }
+
+ public createPair(argsCount: number): PropertyAssignment {
+ const key: string = this.mNameGenerator.getName();
+ this.mArgcFuncMap.set(argsCount, key);
+
+ return factory.createPropertyAssignment(
+ factory.createStringLiteral(key),
+ this.createFunc(argsCount)
+ );
+ }
+
+ private createFunc(argsCount: number): FunctionExpression {
+ let parametersList: ParameterDeclaration[] = [];
+ let parameterNameList: string[] = [];
+
+ // 1. create function parameter
+ for (let i = 0; i < argsCount + 1; i++) {
+ const parameterName: string = this.mNameGenerator.getName();
+ parameterNameList.push(parameterName);
+
+ const funcParameter: ParameterDeclaration = factory.createParameterDeclaration(
+ undefined,
+ undefined,
+ undefined,
+ factory.createIdentifier(parameterName)
+ );
+ parametersList.push(funcParameter);
+ }
+
+ // 2. create call expression parameter
+ const callParametersList: Identifier[] = [];
+ for (let i = 1; i < argsCount + 1; i++) {
+ callParametersList.push(factory.createIdentifier(parameterNameList[i]));
+ }
+
+ // 3. create function body
+ const funcBlock: Block = factory.createBlock(
+ [
+ factory.createReturnStatement(
+ factory.createCallExpression(
+ factory.createIdentifier(parameterNameList[0]),
+ undefined,
+ callParametersList
+ )
+ )
+ ],
+ true
+ );
+
+ return factory.createFunctionExpression(
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ parametersList,
+ undefined,
+ funcBlock
+ );
+ }
+
+ public createCallMapStatement(varName: string, pairArray: PropertyAssignment[]): VariableStatement {
+ const value: ObjectLiteralExpression = this.createCallMapValue(pairArray);
+
+ return factory.createVariableStatement(
+ undefined,
+ factory.createVariableDeclarationList(
+ [
+ factory.createVariableDeclaration(
+ factory.createIdentifier(varName),
+ undefined,
+ undefined,
+ value
+ )
+ ],
+ NodeFlags.Const
+ )
+ );
+ }
+
+ private createCallMapValue(pairArray: PropertyAssignment[]): ObjectLiteralExpression {
+ return factory.createObjectLiteralExpression(
+ pairArray,
+ true
+ );
+ }
+
+ public obfuscateBinaryExpression(binaryExpression: BinaryExpression): Expression {
+ switch (binaryExpression.operatorToken.kind) {
+ case SyntaxKind.MinusToken:
+ return this.createMinusMBA(binaryExpression);
+ case SyntaxKind.CaretToken:
+ // a^b
+ return this.createCaretMBA(binaryExpression);
+ case SyntaxKind.BarToken:
+ // a|b
+ return this.createBarMBA(binaryExpression);
+ case SyntaxKind.AmpersandToken:
+ // a&b
+ return this.createAmpersandMBA(binaryExpression);
+ default:
+ return binaryExpression;
+ }
+ }
+
+ private createMinusMBA(minusExpression: BinaryExpression): BinaryExpression {
+ /**
+ * decimal part: x - y + Math.truc(y) - Math.trunc(x)
+ */
+ function getDecimalMinus(): BinaryExpression {
+ return factory.createBinaryExpression(
+ factory.createBinaryExpression(
+ factory.createBinaryExpression(
+ {...minusExpression.left},
+ SyntaxKind.MinusToken,
+ {...minusExpression.right}
+ ),
+ SyntaxKind.PlusToken,
+ NodeUtils.createTruncExpression(minusExpression.right)
+ ),
+ SyntaxKind.MinusToken,
+ NodeUtils.createTruncExpression(minusExpression.left)
+ );
+ }
+
+ /**
+ * get minus expression of higher 32 bit
+ * trunc(x) - (x|0) - trunc(y) + (y|0)
+ */
+ function getHigh32Minus(): BinaryExpression {
+ return factory.createBinaryExpression(
+ factory.createBinaryExpression(
+ factory.createBinaryExpression(
+ NodeUtils.createTruncExpression(minusExpression.left),
+ SyntaxKind.MinusToken,
+ NodeUtils.createLowerExpression(minusExpression.left)
+ ),
+ SyntaxKind.MinusToken,
+ NodeUtils.createTruncExpression(minusExpression.right)
+ ),
+ SyntaxKind.PlusToken,
+ NodeUtils.createLowerExpression(minusExpression.right)
+ );
+ }
+
+ /**
+ * x - y = (x|0) + ((y^-1) + 1), for lower 32 bit
+ */
+ function method1(): BinaryExpression {
+ const right: ParenthesizedExpression = factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ {...minusExpression.right},
+ SyntaxKind.CaretToken,
+ factory.createPrefixUnaryExpression(
+ SyntaxKind.MinusToken,
+ factory.createNumericLiteral('1')
+ )
+ )
+ ),
+ SyntaxKind.PlusToken,
+ factory.createNumericLiteral('1')
+ )
+ );
+
+ return factory.createBinaryExpression(
+ NodeUtils.createLowerExpression(minusExpression.left),
+ SyntaxKind.PlusToken,
+ right
+ );
+ }
+
+ /**
+ * x - y = (x ^ (~y+1)) - ((-2*x - 1) | (2*y - 1)) - 1
+ */
+ function method2(): BinaryExpression {
+ const first: ParenthesizedExpression = factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ {...minusExpression.left},
+ SyntaxKind.CaretToken,
+ factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ factory.createPrefixUnaryExpression(
+ SyntaxKind.TildeToken,
+ {...minusExpression.right}
+ ),
+ SyntaxKind.PlusToken,
+ factory.createNumericLiteral('1')
+ )
+ )
+ )
+ );
+
+ const secondLeft: BinaryExpression = factory.createBinaryExpression(
+ factory.createBinaryExpression(
+ factory.createPrefixUnaryExpression(
+ SyntaxKind.MinusToken,
+ factory.createNumericLiteral('2')
+ ),
+ SyntaxKind.AsteriskToken,
+ NodeUtils.createLowerExpression(minusExpression.left)
+ ),
+ SyntaxKind.MinusToken,
+ factory.createNumericLiteral('1')
+ );
+
+ const secondRight: BinaryExpression = factory.createBinaryExpression(
+ factory.createBinaryExpression(
+ factory.createNumericLiteral('2'),
+ SyntaxKind.AsteriskToken,
+ NodeUtils.createLowerExpression(minusExpression.right)
+ ),
+ SyntaxKind.MinusToken,
+ factory.createNumericLiteral('1')
+ );
+
+ const second: ParenthesizedExpression = factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ factory.createParenthesizedExpression(secondLeft),
+ SyntaxKind.BarToken,
+ factory.createParenthesizedExpression(secondRight)
+ )
+ );
+
+ return factory.createBinaryExpression(
+ factory.createBinaryExpression(
+ first,
+ SyntaxKind.MinusToken,
+ second
+ ),
+ SyntaxKind.MinusToken,
+ factory.createNumericLiteral('1')
+ );
+ }
+
+ /**
+ * x - y = (x & ~y) - (~x & y)
+ */
+ function method3(): BinaryExpression {
+ const left: ParenthesizedExpression = factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ {...minusExpression.left},
+ SyntaxKind.AmpersandToken,
+ factory.createPrefixUnaryExpression(
+ SyntaxKind.TildeToken,
+ {...minusExpression.right}
+ )
+ )
+ );
+
+ const right: ParenthesizedExpression = factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ factory.createPrefixUnaryExpression(
+ SyntaxKind.TildeToken,
+ {...minusExpression.left}
+ ),
+ SyntaxKind.AmpersandToken,
+ {...minusExpression.right}
+ )
+ );
+
+ return factory.createBinaryExpression(
+ left,
+ SyntaxKind.MinusToken,
+ right
+ );
+ }
+
+ /**
+ * x - y = ~(~x + y)
+ */
+ function method4(): Expression {
+ const inner: BinaryExpression = factory.createBinaryExpression(
+ factory.createPrefixUnaryExpression(
+ SyntaxKind.TildeToken,
+ {...minusExpression.left}
+ ),
+ SyntaxKind.PlusToken,
+ NodeUtils.createLowerExpression(minusExpression.right)
+ );
+
+ return factory.createPrefixUnaryExpression(
+ SyntaxKind.TildeToken,
+ factory.createParenthesizedExpression(inner)
+ );
+ }
+
+ const methodList: (() => Expression)[] = [method1, method2, method3, method4];
+ const mbaMethod: () => Expression = methodList[crypto.randomInt(methodList.length)];
+
+ const decimalPart: BinaryExpression = getDecimalMinus();
+ const highPart: BinaryExpression = getHigh32Minus();
+
+ return factory.createBinaryExpression(
+ factory.createBinaryExpression(
+ mbaMethod(),
+ SyntaxKind.PlusToken,
+ highPart
+ ),
+ SyntaxKind.PlusToken,
+ decimalPart
+ );
+ }
+
+ private createCaretMBA(xorExpression: BinaryExpression): BinaryExpression {
+ /**
+ * x ^ y = (x | y) - (x & y)
+ */
+ function method1(): BinaryExpression {
+ const left: ParenthesizedExpression = factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ {...xorExpression.left},
+ SyntaxKind.BarToken,
+ {...xorExpression.right}
+ )
+ );
+
+ const right: ParenthesizedExpression = factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ {...xorExpression.left},
+ SyntaxKind.AmpersandToken,
+ {...xorExpression.right}
+ )
+ );
+
+ return factory.createBinaryExpression(
+ left,
+ SyntaxKind.MinusToken,
+ right
+ );
+ }
+
+ /**
+ * x ^ y = x + y - 2*(x & y)
+ */
+ function method2(): BinaryExpression {
+ const left: BinaryExpression = factory.createBinaryExpression(
+ NodeUtils.createLowerExpression(xorExpression.left),
+ SyntaxKind.PlusToken,
+ NodeUtils.createLowerExpression(xorExpression.right)
+ );
+
+ const right: BinaryExpression = factory.createBinaryExpression(
+ factory.createNumericLiteral('2'),
+ SyntaxKind.AsteriskToken,
+ factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ {...xorExpression.left},
+ SyntaxKind.AmpersandToken,
+ {...xorExpression.right}
+ )
+ )
+ );
+
+ return factory.createBinaryExpression(
+ left,
+ SyntaxKind.MinusToken,
+ right
+ );
+ }
+
+ const methodList: (() => BinaryExpression)[] = [method1, method2];
+ const mbaMethod: () => BinaryExpression = methodList[crypto.randomInt(methodList.length)];
+ return mbaMethod();
+ }
+
+ private createBarMBA(orExpression: BinaryExpression): BinaryExpression {
+ /**
+ * x | y = (x ^ y) ^ (x & y)
+ */
+ function method1(): BinaryExpression {
+ const left: ParenthesizedExpression = factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ {...orExpression.left},
+ SyntaxKind.CaretToken,
+ {...orExpression.right}
+ )
+ );
+
+ const right: ParenthesizedExpression = factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ {...orExpression.left},
+ SyntaxKind.AmpersandToken,
+ {...orExpression.right}
+ )
+ );
+
+ return factory.createBinaryExpression(
+ left,
+ SyntaxKind.CaretToken,
+ right
+ );
+ }
+
+ /**
+ * x | y = x + y - (x & y)
+ */
+ function method2(): BinaryExpression {
+ const left: BinaryExpression = factory.createBinaryExpression(
+ NodeUtils.createLowerExpression(orExpression.left),
+ SyntaxKind.PlusToken,
+ NodeUtils.createLowerExpression(orExpression.right)
+ );
+
+ const right: ParenthesizedExpression = factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ {...orExpression.left},
+ SyntaxKind.AmpersandToken,
+ {...orExpression.right}
+ )
+ );
+
+ return factory.createBinaryExpression(
+ left,
+ SyntaxKind.MinusToken,
+ right
+ );
+ }
+
+ /**
+ * x | y = (x & y) | (x ^ y)
+ */
+ function method3(): BinaryExpression {
+ const left: ParenthesizedExpression = factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ {...orExpression.left},
+ SyntaxKind.AmpersandToken,
+ {...orExpression.right}
+ )
+ );
+
+ const right: ParenthesizedExpression = factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ {...orExpression.left},
+ SyntaxKind.CaretToken,
+ {...orExpression.right}
+ )
+ );
+
+ return factory.createBinaryExpression(
+ left,
+ SyntaxKind.BarToken,
+ right
+ );
+ }
+
+ const methodList: (() => BinaryExpression)[] = [method1, method2, method3];
+ const mbaMethod: () => BinaryExpression = methodList[crypto.randomInt(methodList.length)];
+ return mbaMethod();
+ }
+
+ private createAmpersandMBA(andExpression: BinaryExpression): Expression {
+ /**
+ * x & y = ~(~x | ~y)
+ */
+ function method1(): Expression {
+ const inner: BinaryExpression = factory.createBinaryExpression(
+ factory.createPrefixUnaryExpression(
+ SyntaxKind.TildeToken,
+ {...andExpression.left}
+ ),
+ SyntaxKind.BarToken,
+ factory.createPrefixUnaryExpression(
+ SyntaxKind.TildeToken,
+ {...andExpression.right}
+ )
+ );
+
+ return factory.createPrefixUnaryExpression(
+ SyntaxKind.TildeToken,
+ factory.createParenthesizedExpression(
+ inner
+ )
+ );
+ }
+
+ /**
+ * x & y = x + y - (x | y)
+ */
+ function method2(): BinaryExpression {
+ const left: BinaryExpression = factory.createBinaryExpression(
+ NodeUtils.createLowerExpression(andExpression.left),
+ SyntaxKind.PlusToken,
+ NodeUtils.createLowerExpression(andExpression.right)
+ );
+
+ const right: ParenthesizedExpression = factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ {...andExpression.left},
+ SyntaxKind.BarToken,
+ {...andExpression.right}
+ )
+ );
+
+ return factory.createBinaryExpression(
+ left,
+ SyntaxKind.MinusToken,
+ right
+ );
+ }
+
+ /**
+ * x & y = (x | y) - (~x & y) - (x & ~y)
+ */
+ function method3(): BinaryExpression {
+ const first: ParenthesizedExpression = factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ {...andExpression.left},
+ SyntaxKind.BarToken,
+ {...andExpression.right}
+ )
+ );
+
+ const second: ParenthesizedExpression = factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ factory.createPrefixUnaryExpression(
+ SyntaxKind.TildeToken,
+ {...andExpression.left}
+ ),
+ SyntaxKind.AmpersandToken,
+ {...andExpression.right}
+ )
+ );
+
+ const third: ParenthesizedExpression = factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ {...andExpression.left},
+ SyntaxKind.AmpersandToken,
+ factory.createPrefixUnaryExpression(
+ SyntaxKind.TildeToken,
+ {...andExpression.right}
+ )
+ )
+ );
+
+ return factory.createBinaryExpression(
+ factory.createBinaryExpression(
+ first,
+ SyntaxKind.MinusToken,
+ second
+ ),
+ SyntaxKind.MinusToken,
+ third
+ );
+ }
+
+ /**
+ * x & y = (x ^ ~y) & x
+ */
+ function method4(): BinaryExpression {
+ const left: ParenthesizedExpression = factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ {...andExpression.left},
+ SyntaxKind.CaretToken,
+ factory.createPrefixUnaryExpression(
+ SyntaxKind.TildeToken,
+ {...andExpression.right}
+ )
+ )
+ );
+
+ return factory.createBinaryExpression(
+ left,
+ SyntaxKind.AmpersandToken,
+ {...andExpression.left}
+ );
+ }
+
+ const methodList: (() => Expression)[] = [method1, method2, method3, method4];
+ const mbaMethod: () => Expression = methodList[crypto.randomInt(methodList.length)];
+ return mbaMethod();
+ }
+}
diff --git a/arkguard/src/transformers/instruction/InstructionObfuscationTransformer.ts b/arkguard/src/transformers/instruction/InstructionObfuscationTransformer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e2ed2843e28235324b84bbd6ae7b635ff06d82a3
--- /dev/null
+++ b/arkguard/src/transformers/instruction/InstructionObfuscationTransformer.ts
@@ -0,0 +1,398 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import * as crypto from 'crypto';
+
+import {
+ factory,
+ isBinaryExpression,
+ isCallExpression,
+ isDecorator,
+ isElementAccessExpression,
+ isIdentifier,
+ isPropertyAccessExpression,
+ isSourceFile,
+ NodeFlags,
+ setParentRecursive,
+ SyntaxKind,
+ visitEachChild
+} from 'typescript';
+
+import type {
+ BinaryExpression,
+ BinaryOperator,
+ Block,
+ CallExpression,
+ CaseOrDefaultClause,
+ Expression,
+ FunctionDeclaration,
+ Identifier,
+ Node,
+ ParameterDeclaration,
+ PropertyAccessExpression,
+ PropertyAssignment, SourceFile,
+ Statement, SwitchStatement,
+ TransformationContext,
+ Transformer,
+ TransformerFactory,
+ VariableStatement
+} from 'typescript';
+
+import type {TransformPlugin} from '../TransformPlugin';
+import type {IOptions} from '../../configs/IOptions';
+import {InstructionObfsMethod} from '../../configs/IInstructionObfuscationOption';
+import type {IInstructionObfuscationOption} from '../../configs/IInstructionObfuscationOption';
+import {InstructionHelper} from './InstructionObfsHelper';
+import {NodeUtils} from '../../utils/NodeUtils';
+import {getNameGenerator, NameGeneratorType} from '../../generator/NameFactory';
+import type {INameGenerator, NameGeneratorOptions} from '../../generator/INameGenerator';
+import {collectExistNames, isObfsIgnoreNode} from '../../utils/TransformUtil';
+
+namespace secharmony {
+ const createInstructionObfuscationFactory = function (option: IOptions): TransformerFactory {
+ let profile: IInstructionObfuscationOption | undefined = option?.mInstructionObfuscation;
+ if (!profile || !profile.mEnable || profile.mThreshold <= 0) {
+ return null;
+ }
+
+ return instructionObfuscationFactory;
+
+ function instructionObfuscationFactory(context: TransformationContext): Transformer {
+ const skipLoop: boolean = profile.mSkipLoop;
+ let instructionHelper: InstructionHelper;
+ let narrowNames: string[] = option?.mNarrowFunctionNames ?? [];
+ // for call expression
+ let varName: string;
+ let pairArray: PropertyAssignment[] = [];
+ let reservedNames: Set;
+ let reservedIdentifiers: Set;
+ let sourceFile: SourceFile;
+
+ // for binary expression
+ let replaceMethod: InstructionObfsMethod = profile.mInstructionObfsMethod;
+ const methodTypeMap: Map = new Map();
+ let deformFuncName: string;
+ const seed: string = '0x' + crypto.randomBytes(1).toString('hex');
+ let simpleDeformed: boolean = false;
+
+ return transformer;
+
+ function transformer(node: Node): Node {
+ if (!isSourceFile(node) || node.fileName.endsWith('.d.ts')) {
+ return node;
+ }
+
+ sourceFile = node;
+ reservedIdentifiers = collectExistNames(node);
+
+ const options: NameGeneratorOptions = {
+ reservedNames: reservedIdentifiers
+ };
+ const nameGenerator: INameGenerator = getNameGenerator(NameGeneratorType.ORDERED, options);
+ instructionHelper = new InstructionHelper(nameGenerator);
+ varName = nameGenerator.getName();
+ deformFuncName = nameGenerator.getName();
+ const functionDeclare: FunctionDeclaration = createSimpleDeformFunction(deformFuncName, seed);
+
+ let obfuscatedAst: Node = visitAst(node);
+
+ reservedNames = instructionHelper.getReservedIdentifiers();
+ if (reservedNames.size > 0) {
+ obfuscatedAst = changeReservedNamesAccess(obfuscatedAst);
+ }
+
+ if (!isSourceFile(obfuscatedAst)) {
+ return node;
+ }
+
+ let newStatements: Statement[] = [...obfuscatedAst.statements];
+ if (simpleDeformed) {
+ newStatements = NodeUtils.randomInsertStatements(newStatements, functionDeclare);
+ }
+
+ if (pairArray.length > 0) {
+ const initStatement: VariableStatement = instructionHelper.createCallMapStatement(varName, pairArray);
+ newStatements = [initStatement, ...newStatements];
+ }
+
+ // must use update, don't create here, otherwise will encounter an issue for printer.
+ const newAst: SourceFile = factory.updateSourceFile(node, newStatements);
+ return setParentRecursive(newAst, true);
+ }
+
+ function visitAst(node: Node): Node {
+ if (isDecorator(node)) {
+ return node;
+ }
+
+ if (skipLoop && NodeUtils.isLoopStatement(node)) {
+ return node;
+ }
+
+ if (!isSourceFile(node) && isObfsIgnoreNode(node, sourceFile)) {
+ return node;
+ }
+
+ // only replace most inner instruction
+ if ((!isCallExpression(node) || !NodeUtils.isMostInnerCallExpression(node)) &&
+ (!isBinaryExpression(node) || !NodeUtils.isMostInnerBinary(node))) {
+ return visitEachChild(node, visitAst, context);
+ }
+
+ const newNode: BinaryExpression | CallExpression = visitEachChild(node, visitAst, context);
+ return replaceInstruction(newNode);
+ }
+
+ /**
+ * change property access to element access of reserved names
+ * @param node
+ */
+ function changeReservedNamesAccess(node: Node): Node {
+ if (!isPropertyAccessExpression(node)) {
+ return visitEachChild(node, changeReservedNamesAccess, context);
+ }
+
+ if (!isIdentifier(node.expression)) {
+ return visitEachChild(node, changeReservedNamesAccess, context);
+ }
+
+ if (!reservedNames.has(node.expression.escapedText.toString())) {
+ return node;
+ }
+
+ const newNode: PropertyAccessExpression = visitEachChild(node, changeReservedNamesAccess, context);
+ return NodeUtils.changePropertyAccessToElementAccess(newNode);
+ }
+
+ function simpleDeformBinary(binaryExpression: BinaryExpression): Expression {
+ if (methodTypeMap.get(binaryExpression.operatorToken.kind) === undefined) {
+ return binaryExpression;
+ }
+
+ if (binaryExpression.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken ||
+ binaryExpression.operatorToken.kind === SyntaxKind.BarBarToken) {
+ return binaryExpression;
+ }
+
+ const type: string = methodTypeMap.get(binaryExpression.operatorToken.kind);
+ const HEX_RADIX: number = 16;
+ const fakeValue: number = parseInt(type, HEX_RADIX) - parseInt(seed, HEX_RADIX);
+ let fakeValueHexStr: string = '0x' + (Math.abs(fakeValue)).toString(HEX_RADIX);
+ if (fakeValue < 0) {
+ fakeValueHexStr = '-' + fakeValueHexStr;
+ }
+
+ simpleDeformed = true;
+ return factory.createCallExpression(
+ factory.createIdentifier(deformFuncName),
+ undefined,
+ [
+ {...binaryExpression.left},
+ {...binaryExpression.right},
+ factory.createNumericLiteral(fakeValueHexStr)
+ ]
+ );
+ }
+
+ function replaceInstruction(node: Node): Node {
+ // judge threshold
+ const RANDOM_MAX: number = 100;
+ const temp: number = crypto.randomInt(RANDOM_MAX);
+ if (temp > RANDOM_MAX * profile.mThreshold) {
+ return node;
+ }
+
+ if (isCallExpression(node)) {
+ if (isPropertyAccessExpression(node.expression) ||
+ isElementAccessExpression(node.expression) ||
+ !isIdentifier(node.expression)) {
+ return node;
+ }
+
+ if (narrowNames.includes((node.expression as Identifier).text)) {
+ return node;
+ }
+
+ return instructionHelper.deformCallExpression(node, varName, pairArray);
+ }
+
+ if (isBinaryExpression(node)) {
+ if (replaceMethod !== InstructionObfsMethod.MBA_EXPRESSION) {
+ return simpleDeformBinary(node);
+ }
+
+ const replacedBinary: Expression = instructionHelper.obfuscateBinaryExpression(node);
+ if (replacedBinary !== node) {
+ return replacedBinary;
+ }
+
+ return simpleDeformBinary(node);
+ }
+
+ return node;
+ }
+
+ function generateMethodTypeMap(): void {
+ const methodList: SyntaxKind[] = [
+ SyntaxKind.PlusToken, SyntaxKind.MinusToken, SyntaxKind.AsteriskToken,
+ SyntaxKind.SlashToken, SyntaxKind.AmpersandToken, SyntaxKind.BarToken,
+ SyntaxKind.CaretToken, SyntaxKind.BarBarToken, SyntaxKind.AmpersandAmpersandToken,
+ SyntaxKind.EqualsEqualsToken, SyntaxKind.ExclamationEqualsToken,
+ SyntaxKind.EqualsEqualsEqualsToken, SyntaxKind.ExclamationEqualsEqualsToken,
+ SyntaxKind.LessThanToken, SyntaxKind.LessThanEqualsToken,
+ SyntaxKind.GreaterThanToken, SyntaxKind.GreaterThanEqualsToken,
+ SyntaxKind.LessThanLessThanToken, SyntaxKind.GreaterThanGreaterThanToken,
+ SyntaxKind.GreaterThanGreaterThanGreaterThanToken,
+ SyntaxKind.PercentToken, SyntaxKind.InstanceOfKeyword,
+ SyntaxKind.InKeyword
+ ];
+
+ const options: NameGeneratorOptions = {
+ hexLength: 2,
+ hexWithPrefixSuffix: false
+ };
+
+ const typeGenerator: INameGenerator = getNameGenerator(NameGeneratorType.HEX, options);
+ methodList.forEach((method) => {
+ methodTypeMap.set(method, '0x' + typeGenerator.getName());
+ });
+ }
+
+ /**
+ * create simple deform function of calculate binary expression
+ * function parameter use common name because name obfuscate will be done after this transformer
+ * index transform prototype: x+y = (x|y) + (x&y)
+ * @param functionName
+ * @param seed
+ * @private
+ */
+ function createSimpleDeformFunction(functionName: string, seed: string): FunctionDeclaration {
+ const parameters: ParameterDeclaration[] = [
+ factory.createParameterDeclaration(
+ undefined,
+ undefined,
+ undefined,
+ factory.createIdentifier('left')
+ ),
+ factory.createParameterDeclaration(
+ undefined,
+ undefined,
+ undefined,
+ factory.createIdentifier('right')
+ ),
+ factory.createParameterDeclaration(
+ undefined,
+ undefined,
+ undefined,
+ factory.createIdentifier('type')
+ )
+ ];
+
+ const valueDeclare: VariableStatement = factory.createVariableStatement(
+ undefined,
+ factory.createVariableDeclarationList(
+ [
+ factory.createVariableDeclaration(
+ factory.createIdentifier('value'),
+ undefined,
+ undefined,
+ factory.createBinaryExpression(
+ factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ factory.createNumericLiteral(seed),
+ SyntaxKind.BarToken,
+ factory.createIdentifier('type')
+ )
+ ),
+ SyntaxKind.PlusToken,
+ factory.createParenthesizedExpression(
+ factory.createBinaryExpression(
+ factory.createNumericLiteral(seed),
+ SyntaxKind.AmpersandToken,
+ factory.createIdentifier('type')
+ )
+ )
+ )
+ )
+ ],
+ NodeFlags.Const
+ )
+ );
+
+ const caseClauses: CaseOrDefaultClause[] = [];
+ generateMethodTypeMap();
+ for (const method of methodTypeMap.keys()) {
+ caseClauses.push(
+ factory.createCaseClause(
+ factory.createNumericLiteral(methodTypeMap.get(method)),
+ [
+ factory.createReturnStatement(
+ factory.createBinaryExpression(
+ factory.createIdentifier('left'),
+ method as BinaryOperator,
+ factory.createIdentifier('right')
+ )
+ )
+ ]
+ )
+ );
+ }
+
+ caseClauses.push(
+ factory.createDefaultClause(
+ [
+ factory.createReturnStatement(
+ factory.createNumericLiteral(seed)
+ )
+ ]
+ )
+ );
+
+ const switchStatement: SwitchStatement = factory.createSwitchStatement(
+ factory.createIdentifier('value'),
+ factory.createCaseBlock(caseClauses)
+ );
+
+ const body: Block = factory.createBlock(
+ [
+ valueDeclare,
+ switchStatement
+ ],
+ true
+ );
+
+ return factory.createFunctionDeclaration(
+ undefined,
+ undefined,
+ undefined,
+ factory.createIdentifier(functionName),
+ undefined,
+ parameters,
+ undefined,
+ body
+ );
+ }
+ }
+ };
+
+ const TRANSFORMER_ORDER: number = 5;
+ export let transformerPlugin: TransformPlugin = {
+ 'name': 'InstructionObfuscationTransformer',
+ 'createTransformerFactory': createInstructionObfuscationFactory,
+ 'order': (1 << TRANSFORMER_ORDER)
+ };
+}
+
+export = secharmony;
diff --git a/arkguard/src/transformers/layout/DisableConsoleTransformer.ts b/arkguard/src/transformers/layout/DisableConsoleTransformer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ee1b5fe02daf0a439f0a6c72611f5caf47fc5da3
--- /dev/null
+++ b/arkguard/src/transformers/layout/DisableConsoleTransformer.ts
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import {
+ factory,
+ isBlock,
+ isCallExpression,
+ isElementAccessExpression,
+ isExpressionStatement,
+ isIdentifier,
+ isPropertyAccessExpression,
+ isSourceFile,
+ setParentRecursive,
+ visitEachChild
+} from 'typescript';
+
+import type {
+ Block,
+ LeftHandSideExpression,
+ Node,
+ NodeArray,
+ SourceFile,
+ Statement,
+ TransformationContext,
+ Transformer,
+ TransformerFactory
+} from 'typescript';
+
+import type {IOptions} from '../../configs/IOptions';
+import type {TransformPlugin} from '../TransformPlugin';
+
+namespace secharmony {
+ const TRANSFORMER_ORDER: number = 1;
+ export let transformerPlugin: TransformPlugin = {
+ 'name': 'disableConsolePlugin',
+ 'order': (1 << TRANSFORMER_ORDER),
+ 'createTransformerFactory': createDisableConsoleFactory
+ };
+
+ export function createDisableConsoleFactory(option: IOptions): TransformerFactory {
+ if (!option.mDisableConsole) {
+ return null;
+ }
+
+ return disableConsoleFactory;
+
+ function disableConsoleFactory(context: TransformationContext): Transformer {
+ return transformer;
+
+ function transformer(node: Node): Node {
+ if (!isSourceFile(node) || node.fileName.endsWith('.d.ts')) {
+ return node;
+ }
+
+ let resultAst: Node = visitAst(node);
+ return setParentRecursive(resultAst, true);
+ }
+
+ /**
+ * delete console log print expression, only support simple format like:
+ * - console.xxx();
+ * - console['xxx']();
+ * @param node
+ */
+ function visitAst(node: Node): Node {
+ if (isSourceFile(node)) {
+ const visitedAst: SourceFile = visitEachChild(node, visitAst, context);
+ const deletedStatements: Statement[] = deleteConsoleStatement(visitedAst.statements);
+
+ return factory.updateSourceFile(node, deletedStatements);
+ }
+
+ if (!isBlock(node)) {
+ return visitEachChild(node, visitAst, context);
+ }
+
+ const visitedBlock: Block = visitEachChild(node, visitAst, context);
+ const newStatements: Statement[] = deleteConsoleStatement(visitedBlock.statements);
+
+ return factory.createBlock(newStatements, true);
+ }
+
+ function deleteConsoleStatement(statements: NodeArray): Statement[] {
+ const reservedStatements: Statement[] = [];
+ statements.forEach((child) => {
+ if (!isSimpleConsoleStatement(child)) {
+ reservedStatements.push(child);
+ }
+ });
+
+ return reservedStatements;
+ }
+
+ function isSimpleConsoleStatement(node: Statement): boolean {
+ if (!isExpressionStatement(node)) {
+ return false;
+ }
+
+ if (!node.expression || !isCallExpression(node.expression)) {
+ return false;
+ }
+
+ const expressionCalled: LeftHandSideExpression = node.expression.expression;
+ if (!expressionCalled) {
+ return false;
+ }
+
+ if (isPropertyAccessExpression(expressionCalled) && expressionCalled.expression) {
+ if (isIdentifier(expressionCalled.expression) && expressionCalled.expression.text === 'console') {
+ return true;
+ }
+ }
+
+ if (isElementAccessExpression(expressionCalled) && expressionCalled.expression) {
+ if (isIdentifier(expressionCalled.expression) && expressionCalled.expression.text === 'console') {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+ }
+}
+
+export = secharmony;
diff --git a/arkguard/src/transformers/layout/DisableHilogTransformer.ts b/arkguard/src/transformers/layout/DisableHilogTransformer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7b9193acfdbfb4ce2786cdbbca5da0d64d92d9a5
--- /dev/null
+++ b/arkguard/src/transformers/layout/DisableHilogTransformer.ts
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import {
+ factory,
+ isBlock,
+ isCallExpression,
+ isElementAccessExpression,
+ isExpressionStatement,
+ isIdentifier,
+ isPropertyAccessExpression,
+ isSourceFile,
+ setParentRecursive,
+ visitEachChild
+} from 'typescript';
+
+import type {
+ Block,
+ LeftHandSideExpression,
+ Node,
+ NodeArray,
+ SourceFile,
+ Statement,
+ TransformationContext,
+ Transformer,
+ TransformerFactory
+} from 'typescript';
+
+import type {IOptions} from '../../configs/IOptions';
+import type {TransformPlugin} from '../TransformPlugin';
+import {OhPackType, isCommentedNode} from '../../utils/TransformUtil';
+import {findOhImportStatement} from '../../utils/OhsUtil';
+
+namespace secharmony {
+ const TRANSFORMER_ORDER: number = 2;
+ export let transformerPlugin: TransformPlugin = {
+ 'name': 'disableHilogPlugin',
+ 'order': (1 << TRANSFORMER_ORDER),
+ 'createTransformerFactory': createDisableHilogFactory
+ };
+
+ export function createDisableHilogFactory(option: IOptions): TransformerFactory {
+ if (!option.mDisableHilog) {
+ return null;
+ }
+
+ return disableHilogFactory;
+
+ function disableHilogFactory(context: TransformationContext): Transformer {
+ let sourceFile: SourceFile;
+ return transformer;
+
+ function transformer(node: Node): Node {
+ if (!isSourceFile(node) || node.fileName.endsWith('.d.ts')) {
+ return node;
+ }
+
+ sourceFile = node;
+ let resultAst: Node = visitAst(node);
+ return setParentRecursive(resultAst, true);
+ }
+
+ function visitAst(node: Node): Node {
+ if (isSourceFile(node)) {
+ const visitedAst: SourceFile = visitEachChild(node, visitAst, context);
+ const deletedStatements: Statement[] = deleteHilogStatement(visitedAst.statements);
+
+ return factory.updateSourceFile(node, deletedStatements);
+ }
+
+ if (!isBlock(node)) {
+ return visitEachChild(node, visitAst, context);
+ }
+
+ const visitedBlock: Block = visitEachChild(node, visitAst, context);
+ const newStatements: Statement[] = deleteHilogStatement(visitedBlock.statements);
+
+ return factory.createBlock(newStatements, true);
+ }
+
+ function deleteHilogStatement(statements: NodeArray): Statement[] {
+ const reservedStatements: Statement[] = [];
+ statements.forEach((child) => {
+ if (isSimpleHilogStatement(child)) {
+ return;
+ }
+
+ if (isHilogImportStatement(child)) {
+ if (isCommentedNode(child, sourceFile)) {
+ reservedStatements.push(child);
+ }
+
+ return;
+ }
+
+ reservedStatements.push(child);
+ });
+
+ return reservedStatements;
+ }
+
+ function isHilogImportStatement(node: Statement): boolean {
+ const ohPackType: OhPackType = findOhImportStatement(node, '@ohos.hilog');
+ return ohPackType !== OhPackType.NONE;
+ }
+
+ function isSimpleHilogStatement(node: Statement): boolean {
+ if (!isExpressionStatement(node)) {
+ return false;
+ }
+
+ if (!node.expression || !isCallExpression(node.expression)) {
+ return false;
+ }
+
+ const expressionCalled: LeftHandSideExpression = node.expression.expression;
+ if (!expressionCalled) {
+ return false;
+ }
+
+ if (isPropertyAccessExpression(expressionCalled) && expressionCalled.expression) {
+ if (isIdentifier(expressionCalled.expression) && expressionCalled.expression.text === 'hilog') {
+ return true;
+ }
+ }
+
+ if (isElementAccessExpression(expressionCalled) && expressionCalled.expression) {
+ if (isIdentifier(expressionCalled.expression) && expressionCalled.expression.text === 'hilog') {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+ }
+}
+
+export = secharmony;
diff --git a/arkguard/src/transformers/layout/SimplifyTransformer.ts b/arkguard/src/transformers/layout/SimplifyTransformer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fbea88e0968784abf0da44165c9b0967e93dc173
--- /dev/null
+++ b/arkguard/src/transformers/layout/SimplifyTransformer.ts
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import {
+ factory,
+ isBlock,
+ isExpressionStatement,
+ isReturnStatement,
+ isSourceFile,
+ isVariableStatement,
+ setParentRecursive,
+ SyntaxKind,
+ visitEachChild,
+ isStringLiteral,
+} from 'typescript';
+
+import type {
+ ExpressionStatement,
+ Node,
+ NodeFlags,
+ Statement,
+ TransformationContext,
+ Transformer,
+ TransformerFactory,
+ VariableDeclaration,
+ VariableStatement,
+ ModifiersArray,
+ SourceFile,
+ Block,
+ Expression
+} from 'typescript';
+
+import type {IOptions} from '../../configs/IOptions';
+import type {TransformPlugin} from '../TransformPlugin';
+import {isCommentedNode, isSuperCallStatement} from '../../utils/TransformUtil';
+
+namespace secharmony {
+ const TRANSFORMER_ORDER: number = 10;
+ export let transformerPlugin: TransformPlugin = {
+ 'name': 'simplifyPlugin',
+ 'order': (1 << TRANSFORMER_ORDER),
+ 'createTransformerFactory': createSimplifyFactory
+ };
+
+ export function createSimplifyFactory(option: IOptions): TransformerFactory {
+ if (!option.mSimplify) {
+ return null;
+ }
+
+ return simplifyFactory;
+
+ function simplifyFactory(context: TransformationContext): Transformer {
+ const MIN_STATEMENTS_LEN = 2;
+ let sourceFile: SourceFile;
+ return transformer;
+
+ function transformer(node: Node): Node {
+ if (!isSourceFile(node) || node.fileName.endsWith('.d.ts')) {
+ return node;
+ }
+
+ sourceFile = node;
+ return setParentRecursive(visitStatements(node), true);
+ }
+
+ function visitStatements(node: Node): Node {
+ if (!isSourceFile(node) && !isBlock(node)) {
+ return visitEachChild(node, visitStatements, context);
+ }
+
+ const simplified: SourceFile | Block = visitEachChild(node, visitStatements, context);
+ if (node.statements.length < MIN_STATEMENTS_LEN) {
+ return node;
+ }
+
+ return simplifyStatements(simplified);
+ }
+
+ /**
+ * use variable statement merge and expression merge to simplify code
+ * @param node
+ */
+ function simplifyStatements(node: Node): Node {
+ if (!isSourceFile(node) && !isBlock(node)) {
+ return node;
+ }
+
+ let simplifiedStatements: Statement[] = [];
+ const continuousStatements: Statement[] = [];
+ let nodeFlag: NodeFlags = undefined;
+ let modifiers: ModifiersArray = undefined;
+ let preType: SyntaxKind | undefined = undefined;
+
+ function mergeArray(): void {
+ if (continuousStatements.length < MIN_STATEMENTS_LEN) {
+ simplifiedStatements = [...simplifiedStatements, ...continuousStatements];
+ return;
+ }
+
+ if (preType === SyntaxKind.VariableStatement) {
+ simplifiedStatements.push(mergeVariableStatements(continuousStatements as VariableStatement[]));
+ return;
+ }
+
+ if (preType === SyntaxKind.ExpressionStatement) {
+ simplifiedStatements.push(mergeExpression(continuousStatements as ExpressionStatement[]));
+ }
+ }
+
+ function doMerge(currentType: SyntaxKind | undefined, child: Statement | undefined): void {
+ if (preType === currentType) {
+ if (preType !== SyntaxKind.VariableStatement) {
+ return;
+ }
+
+ if (nodeFlag === (child as VariableStatement).declarationList.flags) {
+ if (!modifiers && !child.modifiers) {
+ return;
+ }
+
+ let isSame: boolean = true;
+ if (modifiers && child.modifiers && modifiers.length === child.modifiers.length) {
+ modifiers.forEach((modifier, index) => {
+ if (modifier.kind !== child.modifiers[index].kind) {
+ isSame = false;
+ }
+ });
+ } else {
+ isSame = false;
+ }
+
+ if (isSame) {
+ return;
+ }
+ }
+
+ mergeArray();
+ nodeFlag = (child as VariableStatement).declarationList.flags;
+ modifiers = child.modifiers;
+ continuousStatements.length = 0;
+ return;
+ }
+
+ if (preType === SyntaxKind.VariableStatement) {
+ nodeFlag = undefined;
+ modifiers = undefined;
+ mergeArray();
+ } else if (preType === SyntaxKind.ExpressionStatement) {
+ mergeArray();
+ }
+
+ continuousStatements.length = 0;
+ preType = currentType;
+ }
+
+ node.statements.forEach((child) => {
+ if (isCommentedNode(child, sourceFile) ||
+ (isExpressionStatement(child) && isStringLiteral(child.expression)) ||
+ isSuperCallStatement(child)
+ ) {
+ doMerge(undefined, undefined);
+ simplifiedStatements.push(child);
+ return;
+ }
+
+ if (isVariableStatement(child)) {
+ doMerge(SyntaxKind.VariableStatement, child);
+ continuousStatements.push(child);
+ nodeFlag = child.declarationList.flags;
+ modifiers = child.modifiers;
+ return;
+ }
+
+ if (isExpressionStatement(child)) {
+ doMerge(SyntaxKind.ExpressionStatement, child);
+ continuousStatements.push(child);
+ return;
+ }
+
+ if (isReturnStatement(child) && child.expression !== undefined) {
+ doMerge(SyntaxKind.ExpressionStatement, child);
+ continuousStatements.push(child);
+ doMerge(undefined, undefined);
+ return;
+ }
+
+ // do merge on continuous stopped
+ doMerge(undefined, child);
+ simplifiedStatements.push(child);
+ });
+
+ doMerge(undefined, undefined);
+
+ if (isSourceFile(node)) {
+ return factory.updateSourceFile(node, simplifiedStatements);
+ }
+
+ return factory.createBlock(simplifiedStatements, true);
+ }
+
+ /**
+ * merge variable statement, need same type and same modifier variable and continuous
+ * @param variableStatements
+ */
+ function mergeVariableStatements(variableStatements: VariableStatement[]): VariableStatement {
+ let variableDeclarations: VariableDeclaration[] = [];
+ variableStatements.forEach((statement) => {
+ variableDeclarations = [...variableDeclarations, ...statement.declarationList.declarations];
+ });
+
+ return factory.createVariableStatement(
+ variableStatements[0].modifiers,
+ factory.createVariableDeclarationList(
+ variableDeclarations,
+ variableStatements[0].declarationList.flags
+ )
+ );
+ }
+
+ /**
+ * merge expression, include:
+ * - continuous expression like a=a+1; b=b+1;
+ */
+ function mergeExpression(expressionStatements: ExpressionStatement[]): Statement {
+ let pos: number = 1;
+ let expression: Expression = expressionStatements[0].expression;
+ const statementsLength: number = expressionStatements.length;
+ while (pos < statementsLength) {
+ expression = factory.createBinaryExpression(
+ expression,
+ SyntaxKind.CommaToken,
+ expressionStatements[pos].expression
+ );
+ pos += 1;
+ }
+
+ if (isReturnStatement(expressionStatements[statementsLength - 1])) {
+ return factory.createReturnStatement(expression);
+ }
+
+ return factory.createExpressionStatement(expression);
+ }
+ }
+ }
+}
+
+export = secharmony;
diff --git a/arkguard/src/transformers/oh/HideOhApiTransformer.ts b/arkguard/src/transformers/oh/HideOhApiTransformer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..50ae52abd866b51987f34d159a49d680ca38c3c1
--- /dev/null
+++ b/arkguard/src/transformers/oh/HideOhApiTransformer.ts
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import {
+ factory,
+ isBlock,
+ isElementAccessExpression,
+ isPropertyAccessExpression,
+ isSourceFile,
+ isStringLiteral,
+ setParentRecursive,
+ visitEachChild
+} from 'typescript';
+
+import type {
+ Block,
+ CallExpression,
+ Node,
+ NodeArray,
+ SourceFile,
+ Statement,
+ TransformationContext,
+ Transformer,
+ TransformerFactory
+} from 'typescript';
+
+import type {IOptions} from '../../configs/IOptions';
+import type {TransformPlugin} from '../TransformPlugin';
+import {collectExistNames, OhPackType} from '../../utils/TransformUtil';
+import {findOhImportStatement} from '../../utils/OhsUtil';
+import type {INameGenerator, NameGeneratorOptions} from '../../generator/INameGenerator';
+import {getNameGenerator, NameGeneratorType} from '../../generator/NameFactory';
+
+namespace secharmony {
+ const TRANSFORMER_ORDER: number = 3;
+ export let transformerPlugin: TransformPlugin = {
+ 'name': 'hideOhApiPlugin',
+ 'order': (1 << TRANSFORMER_ORDER),
+ 'createTransformerFactory': createHideOhApiFactory
+ };
+
+ interface OhHiddenApiInfo {
+ moduleNames: Set,
+ apis: Set
+ }
+
+ export function createHideOhApiFactory(option: IOptions): TransformerFactory {
+ if (!option.mHideOhApi || !option.mHideOhApi.mEnable) {
+ return null;
+ }
+
+ if (!option.mHideOhApi.mProtectedApi || option.mHideOhApi.mProtectedApi.length < 1) {
+ return null;
+ }
+
+ return hideOhApiFactory;
+
+ function hideOhApiFactory(context: TransformationContext): Transformer {
+ let nameGenerator: INameGenerator;
+ let ohHiddenApiInfo: OhHiddenApiInfo;
+
+ return transformer;
+
+ function transformer(node: Node): Node {
+ if (!isSourceFile(node) || node.fileName.endsWith('.d.ts')) {
+ return node;
+ }
+
+ const reservedIdentifiers: Set = collectExistNames(node);
+ const options: NameGeneratorOptions = {
+ reservedNames: reservedIdentifiers
+ };
+ nameGenerator = getNameGenerator(NameGeneratorType.ORDERED, options);
+
+ ohHiddenApiInfo = processOhApi(option.mHideOhApi.mProtectedApi);
+
+ let resultAst: Node = visitAst(node);
+ return setParentRecursive(resultAst, true);
+ }
+
+ function visitAst(node: Node): Node {
+ if (isSourceFile(node)) {
+ const hiddenNode: SourceFile = visitEachChild(node, visitAst, context);
+ const newStatements: Statement[] = hideStatements(hiddenNode.statements, nameGenerator, ohHiddenApiInfo, context);
+ return factory.updateSourceFile(hiddenNode, newStatements);
+ }
+
+ if (isBlock(node)) {
+ const hiddenNode: Block = visitEachChild(node, visitAst, context);
+ const newStatements: Statement[] = hideStatements(hiddenNode.statements, nameGenerator, ohHiddenApiInfo, context);
+ if (newStatements === undefined) {
+ return hiddenNode;
+ }
+
+ return factory.createBlock(newStatements, true);
+ }
+
+ return visitEachChild(node, visitAst, context);
+ }
+ }
+ }
+
+ function hideStatements(statements: NodeArray, nameGenerator: INameGenerator, ohHiddenApiInfo: OhHiddenApiInfo,
+ context: TransformationContext): Statement[] {
+ let newStatements: Statement[] = [...statements];
+ const apiHiddenMap: Map = new Map();
+
+ for (let i = 0; i < statements.length; i++) {
+ // 1. hide api import
+ for (const module of ohHiddenApiInfo.moduleNames) {
+ const ohPackType: OhPackType = findOhImportStatement(statements[i], module);
+ if (ohPackType === OhPackType.NONE) {
+ continue;
+ }
+
+ const moduleStr: string = ohPackType === OhPackType.JS_BUNDLE ? module : module.substring('@ohos.'.length);
+ const hiddenFuncName: string = nameGenerator.getName();
+ const hiddenStatement: Statement = createHiddenStatement(hiddenFuncName, moduleStr);
+
+ newStatements[i] = hideOhStr(statements[i], hiddenFuncName, moduleStr, context);
+ newStatements.push(hiddenStatement);
+ break;
+ }
+
+ // 2. hide api
+ newStatements[i] = hideOhApi(newStatements[i], ohHiddenApiInfo.apis, nameGenerator, context, apiHiddenMap);
+ }
+
+ for (const key of apiHiddenMap.keys()) {
+ newStatements.push(createHiddenStatement(apiHiddenMap.get(key), key));
+ }
+
+ return newStatements;
+ }
+
+ function hideOhStr(node: Statement, hiddenFuncName: string, hiddenStr: string, context: TransformationContext): Statement {
+ let visit = (node: Node): Node => {
+ if (isStringLiteral(node) && node.text === hiddenStr) {
+ return factory.createCallExpression(factory.createIdentifier(hiddenFuncName), undefined, []);
+ }
+
+ return visitEachChild(node, visit, context);
+ };
+
+ return visit(node) as Statement;
+ }
+
+ function hideOhApi(node: Statement, apiNames: Set, nameGenerator: INameGenerator, context: TransformationContext, apiHiddenMap): Statement {
+ let visit = (node: Node): Node => {
+ if (isBlock(node)) {
+ return node;
+ }
+
+ if (isPropertyAccessExpression(node)) {
+ if (!apiNames.has(node.name.text)) {
+ return node;
+ }
+
+ const hiddenFuncName: string = apiHiddenMap.has(node.name.text) ?
+ apiHiddenMap.get(node.name.text) : nameGenerator.getName();
+ if (!apiHiddenMap.has(node.name.text)) {
+ apiHiddenMap.set(node.name.text, hiddenFuncName);
+ }
+
+ const hiddenCall: CallExpression = factory.createCallExpression(
+ factory.createIdentifier(hiddenFuncName),
+ undefined,
+ []
+ );
+ return factory.createElementAccessExpression(node.expression, hiddenCall);
+ }
+
+ if (isElementAccessExpression(node)) {
+ if (!isStringLiteral(node.argumentExpression)) {
+ return node;
+ }
+
+ if (!apiNames.has(node.argumentExpression.text)) {
+ return node;
+ }
+
+ const hiddenFuncName: string = apiHiddenMap.has(node.argumentExpression.text) ?
+ apiHiddenMap.get(node.argumentExpression.text) : nameGenerator.getName();
+ if (!apiHiddenMap.has(node.argumentExpression.text)) {
+ apiHiddenMap.set(node.argumentExpression.text, hiddenFuncName);
+ }
+
+ const hiddenCall: CallExpression = factory.createCallExpression(
+ factory.createIdentifier(hiddenFuncName),
+ undefined,
+ []);
+ return factory.createElementAccessExpression(node.expression, hiddenCall);
+ }
+
+ return visitEachChild(node, visit, context);
+ };
+
+ return visit(node) as Statement;
+ }
+
+ /**
+ * process api list to get module and api function
+ * @param apiList
+ * @private
+ */
+ function processOhApi(apiList: string[]): OhHiddenApiInfo {
+ let apiInfo: OhHiddenApiInfo = {
+ moduleNames: new Set(),
+ apis: new Set()
+ };
+
+ for (const api of apiList) {
+ // check format
+ const MIN_OFFSET = 2;
+ if (!api.startsWith('@ohos') || !api.includes('.') || api.lastIndexOf('.') > api.length - MIN_OFFSET) {
+ continue;
+ }
+
+ // extract api
+ apiInfo.moduleNames.add(api.substring(0, api.lastIndexOf('.')));
+ apiInfo.apis.add(api.substring(api.lastIndexOf('.') + 1));
+ }
+
+ return apiInfo;
+ }
+
+ function createHiddenStatement(hiddenFuncName: string, hiddenStr: string): Statement {
+ return factory.createFunctionDeclaration(
+ undefined,
+ undefined,
+ undefined,
+ factory.createIdentifier(hiddenFuncName),
+ undefined,
+ [],
+ undefined,
+ factory.createBlock(
+ [
+ factory.createReturnStatement(factory.createStringLiteral(hiddenStr))
+ ], false
+ )
+ );
+ }
+}
+
+export = secharmony;
diff --git a/arkguard/src/transformers/rename/RenameIdentifierTransformer.ts b/arkguard/src/transformers/rename/RenameIdentifierTransformer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b860fe5e010f0369e6c509ce5457a29bf6c1834d
--- /dev/null
+++ b/arkguard/src/transformers/rename/RenameIdentifierTransformer.ts
@@ -0,0 +1,385 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+import {
+ factory,
+ forEachChild,
+ isBreakOrContinueStatement,
+ isIdentifier,
+ isLabeledStatement,
+ isSourceFile,
+ setParentRecursive,
+ visitEachChild,
+} from 'typescript';
+
+import type {
+ Identifier,
+ Node,
+ SourceFile,
+ Symbol,
+ TransformationContext,
+ Transformer,
+ TransformerFactory,
+ TypeChecker
+} from 'typescript';
+
+import {
+ createScopeManager,
+ isClassScope,
+ isGlobalScope,
+ isEnumScope,
+ isInterfaceScope,
+ isObjectLiteralScope
+} from '../../utils/ScopeAnalyzer';
+
+import type {
+ Label,
+ Scope,
+ ScopeManager
+} from '../../utils/ScopeAnalyzer';
+
+import type {INameGenerator, NameGeneratorOptions} from '../../generator/INameGenerator';
+import type {IOptions} from '../../configs/IOptions';
+import type {INameObfuscationOption} from '../../configs/INameObfuscationOption';
+import type {TransformPlugin} from '../TransformPlugin';
+import {getNameGenerator, NameGeneratorType} from '../../generator/NameFactory';
+import {TypeUtils} from '../../utils/TypeUtils';
+import {collectIdentifiers} from '../../utils/TransformUtil';
+import {NodeUtils} from '../../utils/NodeUtils';
+
+namespace secharmony {
+ /**
+ * Rename Identifiers, including:
+ * 1. variable name
+ * 2. function name
+ * 3. label name
+ * 4. class name/interface name/ label name
+ * we need implement some features:
+ * 1. rename identifiers
+ * 2. store/restore name to/from nameCache file.
+ * 3. do scope analysis for identifier obfuscations
+ *
+ * @param option
+ */
+ const createRenameIdentifierFactory = function (option: IOptions): TransformerFactory {
+ const profile: INameObfuscationOption | undefined = option?.mNameObfuscation;
+ if (!profile || !profile.mEnable) {
+ return null;
+ }
+
+ const openTopLevel: boolean = option?.mTopLevel;
+ return renameIdentifierFactory;
+
+ function renameIdentifierFactory(context: TransformationContext): Transformer {
+ let reservedNames: string[] = [...(profile?.mReservedNames ?? []), 'this'];
+ let mangledSymbolNames: Map = new Map();
+ let mangledLabelNames: Map