summaryrefslogtreecommitdiff
path: root/data/extensions/jsr@javascriptrestrictor/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/code_builders.js
parentd167f676a167b1392a4e29f14ddf25613468680b (diff)
Update the JShelter extension to 0.15.2.
Diffstat (limited to 'data/extensions/jsr@javascriptrestrictor/code_builders.js')
-rw-r--r--data/extensions/jsr@javascriptrestrictor/code_builders.js184
1 files changed, 135 insertions, 49 deletions
diff --git a/data/extensions/jsr@javascriptrestrictor/code_builders.js b/data/extensions/jsr@javascriptrestrictor/code_builders.js
index 8173c43..c73da36 100644
--- a/data/extensions/jsr@javascriptrestrictor/code_builders.js
+++ b/data/extensions/jsr@javascriptrestrictor/code_builders.js
@@ -4,6 +4,7 @@
* \author Copyright (C) 2019 Libor Polcak
* \author Copyright (C) 2021 Giorgio Maone
* \author Copyright (C) 2022 Marek Salon
+ * \author Copyright (C) 2023 Martin Zmitko
*
* \license SPDX-License-Identifier: GPL-3.0-or-later
*/
@@ -45,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;
- }` : "";
+ }`;
}
/**
@@ -92,30 +89,35 @@ function define_page_context_function(wrapper) {
else {
code += `${wrapper.wrapping_function_body}`
}
-
code += `
};
- if (WrapHelper.XRAY) {
- let innerF = replacementF;
- replacementF = function(...args) {
+ `;
- // prepare callbacks
- args = args.map(a => typeof a === "function" ? WrapHelper.pageAPI(a) : a);
+ if (typeof browser_polyfill_used === "undefined") {
+ code += `
+ let innerF = replacementF;
+ replacementF = function(...args) {
- let ret = WrapHelper.forPage(innerF.call(this, ...args));
- if (ret) {
- if (ret instanceof xrayWindow.Promise || ret instanceof WrapHelper.unX(xrayWindow).Promise) {
- ret = Promise.resolve(ret);
+ // prepare callbacks
+ args = args.map(a => typeof a === "function" ? WrapHelper.pageAPI(a) : a);
+
+ let ret = WrapHelper.forPage(innerF.call(this, ...args));
+ if (ret) {
+ if (ret instanceof xrayWindow.Promise || ret instanceof WrapHelper.unX(xrayWindow).Promise) {
+ ret = Promise.resolve(ret);
+ }
+ try {
+ ret = WrapHelper.unX(ret);
+ } catch (e) {}
}
- try {
- ret = WrapHelper.unX(ret);
- } catch (e) {}
- }
- return ret;
- }
+ return ret;
+ };
+ `;
}
- exportFunction(replacementF, ${parent_object}, {defineAs: '${parent_object_property}'});
- ${wrapper.post_replacement_code || ''}`
+ code += `
+ exportFunction(replacementF, ${parent_object}, {defineAs: '${parent_object_property}'});
+ ${wrapper.post_replacement_code || ''}
+ `;
return enclose_wrapping2(code, wrapper.wrapping_code_function_name, wrapper.wrapping_code_function_params, wrapper.wrapping_code_function_call_window);
}
@@ -146,23 +148,7 @@ function generate_object_properties(code_spec_obj, fpd_only) {
}
code += `
{
- let obj = ${code_spec_obj.parent_object};
- let prop = "${code_spec_obj.parent_object_property}";
- let descriptor = Object.getOwnPropertyDescriptor(obj, prop);
- if (!descriptor) {
- // let's traverse the prototype chain in search of this property
- for (let proto = Object.getPrototypeOf(obj); proto; proto = Object.getPrototypeOf(obj)) {
- if (descriptor = Object.getOwnPropertyDescriptor(proto, prop)) {
- obj = WrapHelper.unX(obj);
- break;
- }
- }
- if (!descriptor) descriptor = {
- // Originally not a descriptor, fallback
- enumerable: true,
- configurable: true,
- };
- }
+ let descriptor = WrapHelper.getDescriptor(${code_spec_obj.parent_object}, "${code_spec_obj.parent_object_property}");
`
for (let wrap_spec of code_spec_obj.wrapped_properties) {
// variable name used for distinguishing between different original properties of the same wrapper
@@ -329,11 +315,13 @@ var build_code = function(wrapper, ...args) {
Object.setPrototypeOf(${target}, ${source});
}`;
}
- code += `
- if (${wrapper.freeze}) {
- Object.freeze(${wrapper.parent_object}.${wrapper.parent_object_property});
- }
- `;
+ if (wrapper.freeze !== undefined) {
+ code += `
+ if (${wrapper.freeze}) {
+ Object.freeze(${wrapper.parent_object}.${wrapper.parent_object_property});
+ }
+ `;
+ }
return enclose_wrapping(code, ...args);
};
@@ -367,6 +355,80 @@ let joinWrappingCode = code => {
}
/**
+ * Insert WebAssembly initialization code into wrapped injection code.
+ */
+function insert_wasm_code(code) {
+ let wasm_code = (() => {
+ const wasm_memory = new WebAssembly.Memory({initial: 1});
+ // Memory layout:
+ // +-----------------+--------------+----------+---------------------------------------- - -
+ // | CRC table | Xoring table | Reserved | Data
+ // | 256 * u16 | 8 * u32 | |
+ // +-----------------+--------------+----------+---------------------------------------- - -
+ // 0 512 544 1024
+ const crc_offset = 0;
+ const xoring_offset = 512;
+ const reserved_offset = 544;
+ const data_offset = 1024;
+
+ WebAssembly.instantiateStreaming(fetch("/* WASM_URL */"), {env: {memory: wasm_memory}}).then(result => {
+ new Uint16Array(wasm_memory.buffer, crc_offset, crc16_table.length).set(crc16_table);
+ const xoring = new Uint32Array(wasm_memory.buffer, xoring_offset, 8);
+ for (let i = 0; i < 64; i += 8) {
+ xoring[i / 8] = parseInt(domainHash.slice(i, i + 8), 16) >>> 0;
+ }
+
+ wasm = {
+ // Getter and setter for data in WASM memory. Because we need access from page context,
+ // we can't just get a memory view and use it directly. The view needs to be exported to be
+ // usable in the page context on Firefox.
+ // This means that views returned by wasm.get() aren't actually views of the WASM memory,
+ // but rather copies of the data and modifying them won't affect the underlying memory.
+ // We can't export the wasm memory directly either, it is bound to the WASM instance and
+ // it's not possible to export the instance as well.
+ // For constructing views of the correct type, we can't use constructors passed from page context,
+ // a content script constructor must be used. For now, we use just 2 types, so passing a bool
+ // to differentiate is enough.
+ get(length, offset = 0, float = false) {
+ if (float) {
+ return WrapHelper.forPage(new Float32Array(wasm_memory.buffer, data_offset + offset, length));
+ } else {
+ return WrapHelper.forPage(new Uint8Array(wasm_memory.buffer, data_offset + offset, length));
+ }
+ },
+ set(data, offset = 0, float = false) {
+ if (float) {
+ new Float32Array(wasm_memory.buffer, data_offset + offset, data.length).set(data);
+ } else {
+ new Uint8Array(wasm_memory.buffer, data_offset + offset, data.length).set(data);
+ }
+ },
+ // Grow the WASM memory if needed.
+ grow(needed_bytes) {
+ const memory_size = wasm_memory.buffer.byteLength;
+ needed_bytes += data_offset;
+ if (memory_size < needed_bytes) {
+ try {
+ wasm_memory.grow(Math.ceil((needed_bytes - memory_size) / 65536));
+ } catch (e) {
+ return false;
+ }
+ }
+ return true;
+ },
+ // Make WASM exported functions available to wrappers.
+ ...result.instance.exports,
+ ready: true
+ }
+ Object.freeze(wasm);
+ }).catch(e => {
+ });
+ }).toString().replace("/* WASM_URL */", browser.runtime.getURL("farble.wasm"));
+
+ return code.replace("// WASM_CODE //", `(${wasm_code})()`);
+}
+
+/**
* Append wrapped codes to NSCL helpers and create injectable code.
*/
function generate_code(wrapped_code) {
@@ -619,6 +681,24 @@ function generate_code(wrapped_code) {
}
return descriptors ? this.defineProperties(obj, descriptors) && obj : obj;
},
+ getDescriptor(obj, prop) {
+ let descriptor = Object.getOwnPropertyDescriptor(obj, prop);
+ if (!descriptor) {
+ // let's traverse the prototype chain in search of this property
+ for (let proto = Object.getPrototypeOf(obj); proto; proto = Object.getPrototypeOf(obj)) {
+ if (descriptor = Object.getOwnPropertyDescriptor(proto, prop)) {
+ obj = unX(obj);
+ break;
+ }
+ }
+ if (!descriptor) descriptor = {
+ // Originally not a descriptor, fallback
+ enumerable: true,
+ configurable: true,
+ };
+ }
+ return descriptor;
+ },
// WrapHelper.overlay(obj, data)
// Proxies the prototype of the obj object in order to return the properties of the data object
@@ -640,6 +720,12 @@ function generate_code(wrapped_code) {
Object.freeze(WrapHelper);
}
+ // The object available to wrappers later containing farbling WASM optmitimized functions if enabled
+ let wasm = Object.freeze({ready: false});
+
+ // Farbling WebAssembly module initialization placeholder
+ // WASM_CODE //
+
with(unwrappedWindow) {
let window = unwrappedWindow;
let {Proxy} = WrapHelper;