Skip to content

Add standardised patching framework #15

Description

@ruipin

Inspired by some modules like Mess which patch methods using a regex, I have been wondering about standardising an API to do this officially supported by libWrapper, and that attempts to handle possible issues such as conflicts.

This API could be e.g.

libWrapper.patch("module-id", "path.to.method", /match/, "replace");

and for ease-of-use, also support

libWrapper.patch("module-id", "path.to.method",
  [/match1/, "replace1"],
  [/match2/, "replace2"],
  ...,
  [/matchN/, "replaceN"]
);

Each pair would behave exactly like a call to String.prototype.replace, so would also support replacement methods, etc.

libWrapper would then be responsible for working out which method to patch (including, if necessary, modifying a prior patch), and automatically setting up a corresponding OVERRIDE.

  • If there's already an override, this method would fail, unless the given module has a higher priority, in which case the existing override gets discarded (and a conflict is signalled).
  • Someone registering an OVERRIDE that is higher priority than all of the modules that set up a patch will cause the patch to be discarded, similar to the current behaviour when there are two OVERRIDE conflicts.
  • If libWrapper cannot resolve the function to source code, it throws an exception.
  • If any individual patch "pair" leaves the source code unchanged, libWrapper throws an exception. A third parameter can be used to signal that patches are not required.
    • The exception is if the patch is being applied on top of an already patched method, and the current module is higher priority than the existing module(s). In such a case, the existing patches are dropped, and the new module takes over.
  • If the final source code is unchanged from the original (i.e. none of the patch pairs applied successfuly), libWrapper throws an exception.
  • If the final source code fails to parse, libWrapper throws an exception.
  • Patches (or to be more exact, the corresponding OVERRIDE) cannot be unregistered.
  • The 🎁 emoji will be prefixed to the patched function names, to make it obvious in the call stack the method has been modified.

This would mean that two modules patching the same method, as long as their regexes don't overlap, would still be compatible.

Modules would be responsible for catching the exceptions if they require fall-back behaviour. As usual, uncaught exceptions will be raised to the user as errors.

The shim could be given a naive fallback implementation, that just does toString(), replace, and then overwrites the original.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions