mirror of
https://github.com/facebookarchive/prepack.git
synced 2024-09-11 14:46:37 +03:00
adding new __replaceFunctionImplementation_unsafe built-in (#2533)
Summary: Release notes: providing __replaceFunctionImplementation_unsafe built-in This new built-in allows replacing the method implementation (capture environment, body, ...) of source functions. As a result, all method calls executed by the Prepack interpreter will be redirected, and the replacement will carry over to the prepacked code. Pull Request resolved: https://github.com/facebook/prepack/pull/2533 Reviewed By: hermanventer Differential Revision: D9693654 Pulled By: NTillmann fbshipit-source-id: bd28997965e641f58f89f7119fa477c535c0e539
This commit is contained in:
parent
96174b5ebf
commit
1d4bd237d4
@ -551,6 +551,67 @@ export default function(realm: Realm): void {
|
||||
})
|
||||
);
|
||||
|
||||
// Helper function that replaces the implementation of a source function with
|
||||
// the details from another source function body, including the captured
|
||||
// environment, the actual code, etc.
|
||||
// This realizes a form of monkey-patching, enabling mocking a function if
|
||||
// one doesn't control all existing references to that function,
|
||||
// or if the storage location to those references cannot be easily updated.
|
||||
// NOTE: This function affects un-tracked state, so care must be taken
|
||||
// that this helper function is executed at the right time; typically, one
|
||||
// would want to execute this function before any call is executed to that
|
||||
// function. Care must be taken not to make reachable conditionally
|
||||
// defined values. Because of this limitations, this helper function
|
||||
// should be considered only as a last resort.
|
||||
global.$DefineOwnProperty(
|
||||
"__replaceFunctionImplementation_unsafe",
|
||||
new PropertyDescriptor({
|
||||
value: new NativeFunctionValue(
|
||||
realm,
|
||||
"global.__replaceFunctionImplementation_unsafe",
|
||||
"__replaceFunctionImplementation_unsafe",
|
||||
2,
|
||||
(context, [target, source]) => {
|
||||
if (!(target instanceof ECMAScriptSourceFunctionValue)) {
|
||||
throw realm.createErrorThrowCompletion(
|
||||
realm.intrinsics.TypeError,
|
||||
"first argument is not a function with source code"
|
||||
);
|
||||
}
|
||||
if (!(source instanceof ECMAScriptSourceFunctionValue)) {
|
||||
throw realm.createErrorThrowCompletion(
|
||||
realm.intrinsics.TypeError,
|
||||
"second argument is not a function with source code"
|
||||
);
|
||||
}
|
||||
|
||||
// relevant properties for functionValue
|
||||
target.$Environment = source.$Environment;
|
||||
target.$ScriptOrModule = source.$ScriptOrModule;
|
||||
|
||||
// properties for ECMAScriptFunctionValue
|
||||
target.$ConstructorKind = source.$ConstructorKind;
|
||||
target.$ThisMode = source.$ThisMode;
|
||||
target.$HomeObject = source.$HomeObject;
|
||||
target.$FunctionKind = source.$FunctionKind;
|
||||
|
||||
// properties for ECMAScriptSourceFunctionValue
|
||||
target.$Strict = source.$Strict;
|
||||
target.$FormalParameters = source.$FormalParameters;
|
||||
target.$ECMAScriptCode = source.$ECMAScriptCode;
|
||||
target.$HasComputedName = source.$HasComputedName;
|
||||
target.$HasEmptyConstructor = source.$HasEmptyConstructor;
|
||||
target.loc = source.loc;
|
||||
|
||||
return context.$Realm.intrinsics.undefined;
|
||||
}
|
||||
),
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
})
|
||||
);
|
||||
|
||||
global.$DefineOwnProperty(
|
||||
"__IntrospectionError",
|
||||
new PropertyDescriptor({
|
||||
|
14
test/serializer/abstract/ReplaceFunctionBody.js
Normal file
14
test/serializer/abstract/ReplaceFunctionBody.js
Normal file
@ -0,0 +1,14 @@
|
||||
(function() {
|
||||
function f() {
|
||||
return 23;
|
||||
}
|
||||
function g() {
|
||||
return 42;
|
||||
}
|
||||
if (global.__abstract) {
|
||||
global.__replaceFunctionImplementation_unsafe(f, g);
|
||||
global.inspect = f;
|
||||
} else {
|
||||
global.inspect = g;
|
||||
}
|
||||
})();
|
Loading…
Reference in New Issue
Block a user