summaryrefslogtreecommitdiff
path: root/data/extensions/jsr@javascriptrestrictor/fp_code_builders.js
diff options
context:
space:
mode:
authorMark H Weaver <mhw@netris.org>2023-09-27 00:53:30 -0400
committerMark H Weaver <mhw@netris.org>2023-09-27 14:34:35 -0400
commitfa5c0b073214191e6996ba0b5bc8e61560ff822c (patch)
tree38e7133195616f4a4da6c8fe46ab2c77c5a6e9e2 /data/extensions/jsr@javascriptrestrictor/fp_code_builders.js
parentd167f676a167b1392a4e29f14ddf25613468680b (diff)
Update the JShelter extension to 0.15.2.
Diffstat (limited to 'data/extensions/jsr@javascriptrestrictor/fp_code_builders.js')
-rw-r--r--data/extensions/jsr@javascriptrestrictor/fp_code_builders.js204
1 files changed, 79 insertions, 125 deletions
diff --git a/data/extensions/jsr@javascriptrestrictor/fp_code_builders.js b/data/extensions/jsr@javascriptrestrictor/fp_code_builders.js
index 4378a84..02467fa 100644
--- a/data/extensions/jsr@javascriptrestrictor/fp_code_builders.js
+++ b/data/extensions/jsr@javascriptrestrictor/fp_code_builders.js
@@ -2,6 +2,7 @@
* \brief Functions that help to automate process of building wrapping code for FPD module
*
* \author Copyright (C) 2021 Marek Salon
+ * \author Copyright (C) 2023 Martin Zmitko
*
* \license SPDX-License-Identifier: GPL-3.0-or-later
*/
@@ -19,28 +20,6 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
-/** \file
- *
- * \brief This file is part of Fingerprint Detector (FPD) and contains helper functions for automated wrappers creation.
- * File also contains loading routine for FPD configuration files (groups-lvl_X.json, wrappers-lvl_X.json, etc...).
- *
- * \ingroup FPD
- */
-
-//DEF_FPD_FILES_S
-var fp_config_files = ["groups-lvl_0", "groups-lvl_1", "wrappers-lvl_0_1"]
-//DEF_FPD_FILES_E
-
-/**
- * The object carrying code for builded FPD wrappers
- */
-var fp_wrapped_codes = {};
-
-/**
- * Object containing parsed input from JSON configuration files of FPD module.
- */
-var fp_levels = {};
-
/**
* Additional wrappers for specialized purposes.
*/
@@ -113,92 +92,46 @@ var additional_wrappers = [
}
]
-/// \cond (Exclude this section from the doxygen documentation. If this section is not excluded, it is documented as a separate function.)
-{
- // parse input files into fp_levels for each level, generate wrapping code and initialize FPD module
- let loadFpdConfig = async () => {
- for (let file of fp_config_files) {
- try {
- let config = JSON.parse(await readFile(browser.runtime.getURL(`fp_config/${file}.json`)));
- let file_splitted = file.split("-");
- let file_levels = file_splitted[1].split("_").filter(x => x != 'lvl');
- fp_levels[file_splitted[0]] = fp_levels[file_splitted[0]] || {};
- for (let level of file_levels) {
- fp_levels[file_splitted[0]][level] = config;
- }
- }
- catch (e) {
- console.error(e);
- }
+/**
+ * The function that generates wrapping code from FPD wrappers when JSS hasn't wrapped anything.
+ *
+ * \param fpd_wrappers Array of wrappers defined by FPD configuration.
+ *
+ * \returns Injectable code created from FPD wrappers.
+ */
+function fp_generate_from_wrappers(fpd_wrappers) {
+ // define wrapper for each FPD endpoint (using default JSS definition of wrappers)
+ let tmp_build_wrapping_code = {};
+ for (let wrap_item of fpd_wrappers) {
+ if (wrap_item[1]) { // wrap_item.type === "property"
+ tmp_build_wrapping_code[wrap_item[0]] = fp_build_property_wrapper(wrap_item);
}
-
- // merge duplicit entries of the same resource to be wrapped only once
- let mergeWrappers = (sameResources) => {
- let mergeGroups = () => {
- let accArray = [];
- for (let resource of sameResources) {
- accArray.push(...resource.groups);
- }
- return accArray;
- }
-
- return {
- resource: sameResources[0].resource,
- type: sameResources[0].type,
- groups: mergeGroups()
- }
+ else { // wrap_item.type === "function"
+ tmp_build_wrapping_code[wrap_item[0]] = fp_build_function_wrapper(wrap_item);
}
+ }
- for (let level in fp_levels.wrappers) {
- let tmpWrappers = {};
- for (let wrapper of fp_levels.wrappers[level]) {
- if (!Object.keys(tmpWrappers).includes(wrapper.resource)) {
- let sameResources = fp_levels.wrappers[level].filter(x => x.resource == wrapper.resource);
- tmpWrappers[wrapper.resource] = mergeWrappers(sameResources);
- }
- }
- fp_levels.wrappers[level] = Object.values(tmpWrappers);
+ // if there is an additional wrapper for resource, overwrite default definition with it
+ for (let additional_item of additional_wrappers) {
+ let { parent_object, parent_object_property } = additional_item;
+ let resource = `${parent_object}.${parent_object_property}`;
+ if (resource in tmp_build_wrapping_code) {
+ tmp_build_wrapping_code[resource] = additional_item;
}
+ }
- for (let level in fp_levels.wrappers) {
- // define wrapper for each FPD endpoint (using default JSS definition of wrappers)
- let tmp_build_wrapping_code = {};
- for (let wrap_item of fp_levels.wrappers[level]) {
- if (wrap_item.type == "property") {
- tmp_build_wrapping_code[wrap_item.resource] = fp_build_property_wrapper(wrap_item);
- }
- else if (wrap_item.type == "function") {
- tmp_build_wrapping_code[wrap_item.resource] = fp_build_function_wrapper(wrap_item);
- }
- }
-
- // if there is an additional wrapper for resource, overwrite default definition with it
- for (let additional_item of additional_wrappers) {
- let { parent_object, parent_object_property } = additional_item;
- let resource = `${parent_object}.${parent_object_property}`;
- if (resource in tmp_build_wrapping_code) {
- tmp_build_wrapping_code[resource] = additional_item;
- }
- }
-
- // transform each wrapper to wrapping code and index it in memory for quick access
- fp_wrapped_codes[level] = {};
- for (let build_item in tmp_build_wrapping_code) {
- try {
- fp_wrapped_codes[level][build_item] = build_code(tmp_build_wrapping_code[build_item]);
- } catch (e) {
- console.error(e);
- fp_wrapped_codes[level][build_item] = "";
- }
- }
+ // transform each wrapper to wrapping code
+ let fp_wrapped_codes = {};
+ for (let build_item in tmp_build_wrapping_code) {
+ try {
+ fp_wrapped_codes[build_item] = build_code(tmp_build_wrapping_code[build_item]);
+ } catch (e) {
+ console.error(e);
+ fp_wrapped_codes[build_item] = "";
}
-
- // initialize FPD module (background script and event listeners)
- initFpd();
}
- loadFpdConfig();
+ return fp_wrapped_codes;
}
-/// \endcond
/**
* The function that appends FPD wrappers into injectable code, if JSS hasn't wrapped certain FPD endpoints already.
@@ -209,26 +142,24 @@ var additional_wrappers = [
*
* \returns Modified injectable code that also contains FPD wrapping code.
*/
-function fp_update_wrapping_code(code, jss_wrappers, fpd_level) {
- let fpd_wrappers = Object.keys(fp_wrapped_codes[fpd_level])
- .filter(key => !jss_wrappers.map(x => x[0]).includes(key))
- .reduce((obj, key) => {
- obj[key] = fp_wrapped_codes[fpd_level][key];
- return obj;
- }, {});
- let fpd_code = joinWrappingCode(Object.values(fpd_wrappers));
+function fp_update_wrapping_code(code, jss_wrappers, fpd_wrappers) {
+ const jss_wrapper_resources = jss_wrappers.map(x => x[0]);
+ const fpd_wrappers_filtered = fpd_wrappers.filter(w => !jss_wrapper_resources.includes(w[0]));
+ const fpd_wrapped_codes = fp_generate_from_wrappers(fpd_wrappers_filtered);
+ const fpd_code = joinWrappingCode(Object.values(fpd_wrapped_codes));
return code.replace("// FPD_S\n", `// FPD_S\n ${fpd_code}`);
}
/**
* The function that creates injectable code specifically for FPD wrappers in case that JSS hasn't wrapped anything.
*
- * \param fpd_level Identifier of the current FPD level/config.
+ * \param fpd_wrappers Array of wrappers defined by FPD configuration.
*
* \returns Injectable code containing only FPD wrapping code.
*/
-function fp_generate_wrapping_code(fpd_level) {
- return generate_code("// FPD_S\n" + joinWrappingCode(Object.values(fp_wrapped_codes[fpd_level])) + "\n// FPD_E");
+function fp_generate_wrapping_code(fpd_wrappers) {
+ let fpd_wrapped_codes = fp_generate_from_wrappers(fpd_wrappers);
+ return generate_code("// FPD_S\n" + joinWrappingCode(Object.values(fpd_wrapped_codes)) + "\n// FPD_E");
}
/**
@@ -240,10 +171,10 @@ function fp_generate_wrapping_code(fpd_level) {
* \returns Object consisting of two properties (path, name) for given resource.
*/
function split_resource(text) {
- var index = text.lastIndexOf('.');
- return {
+ var index = text.lastIndexOf('.');
+ return {
path: text.slice(0, index),
- name: text.slice(index + 1)
+ name: text.slice(index + 1)
}
}
@@ -257,14 +188,10 @@ function split_resource(text) {
function fp_build_property_wrapper(wrap_item) {
// return object initialization
var wrapper_object = {};
-
- // get unique array of property types (set, get), if property not defined => implicit get
- var propTypes = Array.from(new Set(wrap_item.groups.map(
- (x) => { return x.property != undefined ? x.property : "get" })));
// if properties to wrap exist, create property wrapper based on wrap_item input
- if (propTypes.size != 0) {
- var resource_splitted = split_resource(wrap_item.resource);
+ if (wrap_item[2].size != 0) {
+ var resource_splitted = split_resource(wrap_item[0]);
wrapper_object = {
parent_object: resource_splitted["path"],
parent_object_property: resource_splitted["name"],
@@ -276,19 +203,20 @@ function fp_build_property_wrapper(wrap_item) {
parent_object_property: resource_splitted["name"],
wrapped_objects: [],
wrapped_properties: [],
+ report_args: wrap_item[3],
}
],
};
// create post_wrapping_code to wrap every property type
- for (let type of propTypes) {
+ for (let type of wrap_item[2]) {
// save original resource - get property from descriptor, if do not exists, save it directly
wrapper_object.post_wrapping_code[0].wrapped_objects.push({
original_name: `
Object.getOwnPropertyDescriptor(${resource_splitted["path"]}, "${resource_splitted["name"]}") ?
Object.getOwnPropertyDescriptor(${resource_splitted["path"]}, "${resource_splitted["name"]}")["${type}"] :
- ${type == "get" ? wrap_item.resource : undefined}
+ ${type == "get" ? wrap_item[0] : undefined}
`,
wrapped_name: `originalD_${type}`,
});
@@ -313,8 +241,8 @@ function fp_build_property_wrapper(wrap_item) {
* \returns New declarative function wrapper supported by code_builder (same structure as explicitly defined wrappers).
*/
function fp_build_function_wrapper(wrap_item) {
- var resource_splitted = split_resource(wrap_item.resource);
-
+ var resource_splitted = split_resource(wrap_item[0]);
+
var wrapper_object = {
parent_object: resource_splitted["path"],
parent_object_property: resource_splitted["name"],
@@ -325,11 +253,37 @@ function fp_build_function_wrapper(wrap_item) {
wrapped_name: `originalF_${resource_splitted["name"]}`
}],
wrapping_function_args: "...args",
-
+
// call original function on return with same arguments and context (do not change semantics)
wrapping_function_body: `
return originalF_${resource_splitted["name"]}.call(this, ...args);
`,
+ report_args: wrap_item[3],
};
return wrapper_object;
}
+
+/**
+ * The function that adds argument reporting settings to every JSS wrapper definition where specified by FPD configuration.
+ * This is for removing unnecessary reporting of arguments in cases where the arguments may be large
+ * (such as arrays for image/audio data), which results in their slow synchronous serialization.
+ *
+ * \param fpd_wrappers Array of wrappers defined by FPD configuration.
+ */
+function fp_append_reporting_to_jss_wrappers(fpd_wrappers) {
+ const resources_with_reporting = new Set(fpd_wrappers.map(w => w[3] ? w[0] : undefined));
+ resources_with_reporting.delete(undefined);
+ function append_reporting(wrapper) {
+ let {parent_object, parent_object_property} = wrapper;
+ let resource = `${parent_object}.${parent_object_property}`;
+ wrapper.report_args = resources_with_reporting.has(resource);
+ }
+
+ for (let wrapper of Object.values(build_wrapping_code)) {
+ append_reporting(wrapper);
+ if (wrapper.post_wrapping_code) {
+ // Objects wrapped in post wrapping code might be tracked as well
+ Object.values(wrapper.post_wrapping_code).forEach(append_reporting);
+ }
+ }
+}