From 9b8225e4d90379369d71ee5c61c027cbe2edbaee Mon Sep 17 00:00:00 2001 From: Martin Zmitko Date: Jul 04 2023 13:13:31 +0000 Subject: Report called arguments based on FPD config FPD wrapper call reports from pages now contain arguments only if specified by FPD wrapper evaulation configuration. This had a large impact on the performance of wrapped calls with large arguments (e.g. image or audio data arrays passed to functions like readPixels) where it was neccessary to serialize, postMessage, and deserialize them. FPD currently doesn't track any call arguments that are likely to get large; the current count of wrappers requiring argument tracking is just 12 (+2 exceptions in fp_code_builders.js that this change doesn't apply to). --- diff --git a/common/code_builders.js b/common/code_builders.js index 936a365..723dd1a 100644 --- a/common/code_builders.js +++ b/common/code_builders.js @@ -46,16 +46,12 @@ function enclose_wrapping2(code, name, params, call_with_window) { */ function create_counter_call(wrapper, type) { let {parent_object, parent_object_property} = wrapper; - let updateCount = `${parent_object}.${parent_object_property}`; - - if ("update_count" in wrapper) { - if (typeof wrapper.update_count === "string") updateCount = wrapper.update_count; - } - - return updateCount ? `if (fp_enabled && fp_${type}_count < 1000) { - updateCount(${JSON.stringify(updateCount)}, "${type}", args.map(x => JSON.stringify(x))); + let resource = `${parent_object}.${parent_object_property}`; + let args = wrapper.report_args ? "args.map(x => JSON.stringify(x))" : "[]" + return `if (fp_enabled && fp_${type}_count < 1000) { + updateCount(${JSON.stringify(resource)}, "${type}", ${args}); fp_${type}_count += 1; - }` : ""; + }`; } /** diff --git a/common/document_start.js b/common/document_start.js index 0a45f7d..de1da13 100644 --- a/common/document_start.js +++ b/common/document_start.js @@ -39,7 +39,8 @@ function configureInjection({currentLevel, fpdWrappers, domainHash}) { hash.update(JSON.stringify(domainHash)); domainHash = hash.hex(); } - + // Append argument reporting setting to JSS wrapper definitions + fp_append_reporting_to_jss_wrappers(fpdWrappers); // Generate wrapping code var code = wrap_code(currentLevel.wrappers); // Generate FPD wrapping code diff --git a/common/fp_code_builders.js b/common/fp_code_builders.js index 0ff63d4..02467fa 100644 --- a/common/fp_code_builders.js +++ b/common/fp_code_builders.js @@ -203,6 +203,7 @@ function fp_build_property_wrapper(wrap_item) { parent_object_property: resource_splitted["name"], wrapped_objects: [], wrapped_properties: [], + report_args: wrap_item[3], } ], }; @@ -257,6 +258,32 @@ function fp_build_function_wrapper(wrap_item) { 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); + } + } +} diff --git a/common/fp_levels.js b/common/fp_levels.js index 7d57b38..d6db3ab 100644 --- a/common/fp_levels.js +++ b/common/fp_levels.js @@ -91,6 +91,8 @@ var fp_levels = {}; w.type === "property" ? 1 : 0, // Array specifying property types to wrap (getter, setter or both) Array.from(new Set(w.groups.map(x => x.property != undefined ? x.property : "get"))), + // Specify if arguments should be sent for evaulation + w.groups.some(group => "arguments" in group) ? 1 : 0, ]); }