2024-11-14 11:15:18 +01:00
|
|
|
#import <Foundation/Foundation.h>
|
|
|
|
|
#import <UIKit/UIKit.h>
|
fix: replace speculative Bridgeless hook with RainTweak's verified approach
The RCTInstance/-_loadScriptFromSource: + fake-RCTSource hook from the
previous commit was a plausible guess from RN's public source, but
codeberg.org/raincord/RainTweak - an actively-shipping loader for a sibling
Revenge/Bunny fork - proves both the Bridgeless diagnosis correct (its %ctor
refuses to run below Discord v332, i.e. pre-Bridgeless) and shows a cleaner,
verified mechanism: hook RCTHost/-instance:didInitializeRuntime:, let
Discord's own bundle load untouched via %orig, then evaluate Revenge's
scripts directly against the live JSI runtime instead of faking another
bundle load.
- Add Headers/JSI.h + Sources/JSI.mm (ported from RainTweak's JSI.mm):
evaluates NSData as JS or Hermes bytecode directly against a
facebook::jsi::Runtime.
- Add Headers/RCTHost.h declaring the hook target's signature (RN ships no
public header for this internal class).
- Vendor Headers/jsi/{jsi.h,jsi-inl.h,instrumentation.h} - Meta's MIT-licensed
JSI headers, which Theos doesn't provide; RainTweak vendors the same files.
- Rewrite Tweak.x -> Tweak.xm (needs C++ for jsi::Runtime&): runRevengeInjection
now takes a plain data/async execute callback, driven by either the new
RCTHost+JSI hook or the legacy RCTCxxBridge hook (kept as a no-cost
fallback), guarded by a didInject flag so only one path actually injects.
- Makefile: build .xm/.mm sources, add -std=c++17 CCFLAGS matching RainTweak.
Still unverified against a real device, but the mechanism itself is no longer
a guess - it's the one running in a comparable, currently-shipping mod.
2026-08-03 10:10:32 -04:00
|
|
|
#import <jsi/jsi.h>
|
2024-11-14 11:15:18 +01:00
|
|
|
#import "Utils.h"
|
|
|
|
|
#import "Logger.h"
|
|
|
|
|
#import "Theme.h"
|
2024-11-14 22:50:08 +01:00
|
|
|
#import "Fonts.h"
|
2024-11-14 11:15:18 +01:00
|
|
|
#import "LoaderConfig.h"
|
fix: replace speculative Bridgeless hook with RainTweak's verified approach
The RCTInstance/-_loadScriptFromSource: + fake-RCTSource hook from the
previous commit was a plausible guess from RN's public source, but
codeberg.org/raincord/RainTweak - an actively-shipping loader for a sibling
Revenge/Bunny fork - proves both the Bridgeless diagnosis correct (its %ctor
refuses to run below Discord v332, i.e. pre-Bridgeless) and shows a cleaner,
verified mechanism: hook RCTHost/-instance:didInitializeRuntime:, let
Discord's own bundle load untouched via %orig, then evaluate Revenge's
scripts directly against the live JSI runtime instead of faking another
bundle load.
- Add Headers/JSI.h + Sources/JSI.mm (ported from RainTweak's JSI.mm):
evaluates NSData as JS or Hermes bytecode directly against a
facebook::jsi::Runtime.
- Add Headers/RCTHost.h declaring the hook target's signature (RN ships no
public header for this internal class).
- Vendor Headers/jsi/{jsi.h,jsi-inl.h,instrumentation.h} - Meta's MIT-licensed
JSI headers, which Theos doesn't provide; RainTweak vendors the same files.
- Rewrite Tweak.x -> Tweak.xm (needs C++ for jsi::Runtime&): runRevengeInjection
now takes a plain data/async execute callback, driven by either the new
RCTHost+JSI hook or the legacy RCTCxxBridge hook (kept as a no-cost
fallback), guarded by a didInject flag so only one path actually injects.
- Makefile: build .xm/.mm sources, add -std=c++17 CCFLAGS matching RainTweak.
Still unverified against a real device, but the mechanism itself is no longer
a guess - it's the one running in a comparable, currently-shipping mod.
2026-08-03 10:10:32 -04:00
|
|
|
#import "JSI.h"
|
|
|
|
|
#import "RCTHost.h"
|
|
|
|
|
|
|
|
|
|
using namespace facebook;
|
2024-11-14 11:15:18 +01:00
|
|
|
|
|
|
|
|
static NSURL *source;
|
|
|
|
|
static BOOL isJailbroken;
|
2024-11-15 11:45:12 +01:00
|
|
|
static NSString *revengePatchesBundlePath;
|
2024-11-14 11:15:18 +01:00
|
|
|
static NSURL *pyoncordDirectory;
|
|
|
|
|
static LoaderConfig *loaderConfig;
|
fix: replace speculative Bridgeless hook with RainTweak's verified approach
The RCTInstance/-_loadScriptFromSource: + fake-RCTSource hook from the
previous commit was a plausible guess from RN's public source, but
codeberg.org/raincord/RainTweak - an actively-shipping loader for a sibling
Revenge/Bunny fork - proves both the Bridgeless diagnosis correct (its %ctor
refuses to run below Discord v332, i.e. pre-Bridgeless) and shows a cleaner,
verified mechanism: hook RCTHost/-instance:didInitializeRuntime:, let
Discord's own bundle load untouched via %orig, then evaluate Revenge's
scripts directly against the live JSI runtime instead of faking another
bundle load.
- Add Headers/JSI.h + Sources/JSI.mm (ported from RainTweak's JSI.mm):
evaluates NSData as JS or Hermes bytecode directly against a
facebook::jsi::Runtime.
- Add Headers/RCTHost.h declaring the hook target's signature (RN ships no
public header for this internal class).
- Vendor Headers/jsi/{jsi.h,jsi-inl.h,instrumentation.h} - Meta's MIT-licensed
JSI headers, which Theos doesn't provide; RainTweak vendors the same files.
- Rewrite Tweak.x -> Tweak.xm (needs C++ for jsi::Runtime&): runRevengeInjection
now takes a plain data/async execute callback, driven by either the new
RCTHost+JSI hook or the legacy RCTCxxBridge hook (kept as a no-cost
fallback), guarded by a didInject flag so only one path actually injects.
- Makefile: build .xm/.mm sources, add -std=c++17 CCFLAGS matching RainTweak.
Still unverified against a real device, but the mechanism itself is no longer
a guess - it's the one running in a comparable, currently-shipping mod.
2026-08-03 10:10:32 -04:00
|
|
|
static BOOL didInject = NO;
|
2024-11-14 11:15:18 +01:00
|
|
|
|
2026-08-03 09:46:46 -04:00
|
|
|
/**
|
|
|
|
|
* Runs the full Revenge injection sequence (loader payload, downloaded bundle, stored theme,
|
fix: replace speculative Bridgeless hook with RainTweak's verified approach
The RCTInstance/-_loadScriptFromSource: + fake-RCTSource hook from the
previous commit was a plausible guess from RN's public source, but
codeberg.org/raincord/RainTweak - an actively-shipping loader for a sibling
Revenge/Bunny fork - proves both the Bridgeless diagnosis correct (its %ctor
refuses to run below Discord v332, i.e. pre-Bridgeless) and shows a cleaner,
verified mechanism: hook RCTHost/-instance:didInitializeRuntime:, let
Discord's own bundle load untouched via %orig, then evaluate Revenge's
scripts directly against the live JSI runtime instead of faking another
bundle load.
- Add Headers/JSI.h + Sources/JSI.mm (ported from RainTweak's JSI.mm):
evaluates NSData as JS or Hermes bytecode directly against a
facebook::jsi::Runtime.
- Add Headers/RCTHost.h declaring the hook target's signature (RN ships no
public header for this internal class).
- Vendor Headers/jsi/{jsi.h,jsi-inl.h,instrumentation.h} - Meta's MIT-licensed
JSI headers, which Theos doesn't provide; RainTweak vendors the same files.
- Rewrite Tweak.x -> Tweak.xm (needs C++ for jsi::Runtime&): runRevengeInjection
now takes a plain data/async execute callback, driven by either the new
RCTHost+JSI hook or the legacy RCTCxxBridge hook (kept as a no-cost
fallback), guarded by a didInject flag so only one path actually injects.
- Makefile: build .xm/.mm sources, add -std=c++17 CCFLAGS matching RainTweak.
Still unverified against a real device, but the mechanism itself is no longer
a guess - it's the one running in a comparable, currently-shipping mod.
2026-08-03 10:10:32 -04:00
|
|
|
* fonts, preloads) and hands each script's data off to `execute`.
|
2026-08-03 09:46:46 -04:00
|
|
|
*
|
fix: replace speculative Bridgeless hook with RainTweak's verified approach
The RCTInstance/-_loadScriptFromSource: + fake-RCTSource hook from the
previous commit was a plausible guess from RN's public source, but
codeberg.org/raincord/RainTweak - an actively-shipping loader for a sibling
Revenge/Bunny fork - proves both the Bridgeless diagnosis correct (its %ctor
refuses to run below Discord v332, i.e. pre-Bridgeless) and shows a cleaner,
verified mechanism: hook RCTHost/-instance:didInitializeRuntime:, let
Discord's own bundle load untouched via %orig, then evaluate Revenge's
scripts directly against the live JSI runtime instead of faking another
bundle load.
- Add Headers/JSI.h + Sources/JSI.mm (ported from RainTweak's JSI.mm):
evaluates NSData as JS or Hermes bytecode directly against a
facebook::jsi::Runtime.
- Add Headers/RCTHost.h declaring the hook target's signature (RN ships no
public header for this internal class).
- Vendor Headers/jsi/{jsi.h,jsi-inl.h,instrumentation.h} - Meta's MIT-licensed
JSI headers, which Theos doesn't provide; RainTweak vendors the same files.
- Rewrite Tweak.x -> Tweak.xm (needs C++ for jsi::Runtime&): runRevengeInjection
now takes a plain data/async execute callback, driven by either the new
RCTHost+JSI hook or the legacy RCTCxxBridge hook (kept as a no-cost
fallback), guarded by a didInject flag so only one path actually injects.
- Makefile: build .xm/.mm sources, add -std=c++17 CCFLAGS matching RainTweak.
Still unverified against a real device, but the mechanism itself is no longer
a guess - it's the one running in a comparable, currently-shipping mod.
2026-08-03 10:10:32 -04:00
|
|
|
* Historically this fed straight into `RCTCxxBridge -executeApplicationScript:url:async:`
|
|
|
|
|
* (React Native's legacy bridge), which is what `execute` still does below for old-arch hosts.
|
|
|
|
|
* On current Discord iOS builds (Bridgeless / New Architecture, confirmed via RainTweak -
|
|
|
|
|
* codeberg.org/raincord/RainTweak, an actively-shipping loader for a sibling Revenge/Bunny fork
|
|
|
|
|
* that explicitly requires "Discord v332 or above" for Bridgeless), that hook point never fires
|
|
|
|
|
* at all, so `execute` is instead wired to `JSI evaluate:` against the live runtime - see the
|
|
|
|
|
* `RCTHost` hook below, which is the verified entry point.
|
2026-08-03 09:46:46 -04:00
|
|
|
*/
|
fix: replace speculative Bridgeless hook with RainTweak's verified approach
The RCTInstance/-_loadScriptFromSource: + fake-RCTSource hook from the
previous commit was a plausible guess from RN's public source, but
codeberg.org/raincord/RainTweak - an actively-shipping loader for a sibling
Revenge/Bunny fork - proves both the Bridgeless diagnosis correct (its %ctor
refuses to run below Discord v332, i.e. pre-Bridgeless) and shows a cleaner,
verified mechanism: hook RCTHost/-instance:didInitializeRuntime:, let
Discord's own bundle load untouched via %orig, then evaluate Revenge's
scripts directly against the live JSI runtime instead of faking another
bundle load.
- Add Headers/JSI.h + Sources/JSI.mm (ported from RainTweak's JSI.mm):
evaluates NSData as JS or Hermes bytecode directly against a
facebook::jsi::Runtime.
- Add Headers/RCTHost.h declaring the hook target's signature (RN ships no
public header for this internal class).
- Vendor Headers/jsi/{jsi.h,jsi-inl.h,instrumentation.h} - Meta's MIT-licensed
JSI headers, which Theos doesn't provide; RainTweak vendors the same files.
- Rewrite Tweak.x -> Tweak.xm (needs C++ for jsi::Runtime&): runRevengeInjection
now takes a plain data/async execute callback, driven by either the new
RCTHost+JSI hook or the legacy RCTCxxBridge hook (kept as a no-cost
fallback), guarded by a didInject flag so only one path actually injects.
- Makefile: build .xm/.mm sources, add -std=c++17 CCFLAGS matching RainTweak.
Still unverified against a real device, but the mechanism itself is no longer
a guess - it's the one running in a comparable, currently-shipping mod.
2026-08-03 10:10:32 -04:00
|
|
|
static BOOL runRevengeInjection(BOOL async, void (^execute)(NSData *data, BOOL async)) {
|
2024-11-15 11:45:12 +01:00
|
|
|
NSBundle *revengePatchesBundle = [NSBundle bundleWithPath:revengePatchesBundlePath];
|
|
|
|
|
if (!revengePatchesBundle) {
|
|
|
|
|
RevengeLog(@"Failed to load RevengePatches bundle from path: %@", revengePatchesBundlePath);
|
2024-11-14 11:15:18 +01:00
|
|
|
showErrorAlert(@"Loader Error", @"Failed to initialize mod loader. Please reinstall the tweak.");
|
2026-08-03 09:46:46 -04:00
|
|
|
return NO;
|
2024-11-14 11:15:18 +01:00
|
|
|
}
|
|
|
|
|
|
2024-11-15 11:45:12 +01:00
|
|
|
NSURL *patchPath = [revengePatchesBundle URLForResource:@"payload-base" withExtension:@"js"];
|
2024-11-14 11:15:18 +01:00
|
|
|
if (!patchPath) {
|
2024-11-15 11:45:12 +01:00
|
|
|
RevengeLog(@"Failed to find payload-base.js in bundle");
|
2024-11-14 11:15:18 +01:00
|
|
|
showErrorAlert(@"Loader Error", @"Failed to initialize mod loader. Please reinstall the tweak.");
|
2026-08-03 09:46:46 -04:00
|
|
|
return NO;
|
2024-11-14 11:15:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NSData *patchData = [NSData dataWithContentsOfURL:patchPath];
|
2024-11-15 11:45:12 +01:00
|
|
|
RevengeLog(@"Injecting loader");
|
fix: replace speculative Bridgeless hook with RainTweak's verified approach
The RCTInstance/-_loadScriptFromSource: + fake-RCTSource hook from the
previous commit was a plausible guess from RN's public source, but
codeberg.org/raincord/RainTweak - an actively-shipping loader for a sibling
Revenge/Bunny fork - proves both the Bridgeless diagnosis correct (its %ctor
refuses to run below Discord v332, i.e. pre-Bridgeless) and shows a cleaner,
verified mechanism: hook RCTHost/-instance:didInitializeRuntime:, let
Discord's own bundle load untouched via %orig, then evaluate Revenge's
scripts directly against the live JSI runtime instead of faking another
bundle load.
- Add Headers/JSI.h + Sources/JSI.mm (ported from RainTweak's JSI.mm):
evaluates NSData as JS or Hermes bytecode directly against a
facebook::jsi::Runtime.
- Add Headers/RCTHost.h declaring the hook target's signature (RN ships no
public header for this internal class).
- Vendor Headers/jsi/{jsi.h,jsi-inl.h,instrumentation.h} - Meta's MIT-licensed
JSI headers, which Theos doesn't provide; RainTweak vendors the same files.
- Rewrite Tweak.x -> Tweak.xm (needs C++ for jsi::Runtime&): runRevengeInjection
now takes a plain data/async execute callback, driven by either the new
RCTHost+JSI hook or the legacy RCTCxxBridge hook (kept as a no-cost
fallback), guarded by a didInject flag so only one path actually injects.
- Makefile: build .xm/.mm sources, add -std=c++17 CCFLAGS matching RainTweak.
Still unverified against a real device, but the mechanism itself is no longer
a guess - it's the one running in a comparable, currently-shipping mod.
2026-08-03 10:10:32 -04:00
|
|
|
execute(patchData, YES);
|
2024-11-14 11:15:18 +01:00
|
|
|
|
|
|
|
|
__block NSData *bundle = [NSData dataWithContentsOfURL:[pyoncordDirectory URLByAppendingPathComponent:@"bundle.js"]];
|
2024-11-15 09:47:28 +01:00
|
|
|
|
2024-11-14 11:15:18 +01:00
|
|
|
dispatch_group_t group = dispatch_group_create();
|
|
|
|
|
dispatch_group_enter(group);
|
|
|
|
|
|
|
|
|
|
NSURL *bundleUrl;
|
|
|
|
|
if (loaderConfig.customLoadUrlEnabled && loaderConfig.customLoadUrl) {
|
|
|
|
|
bundleUrl = loaderConfig.customLoadUrl;
|
2024-11-15 11:45:12 +01:00
|
|
|
RevengeLog(@"Using custom load URL: %@", bundleUrl.absoluteString);
|
2024-11-14 11:15:18 +01:00
|
|
|
} else {
|
2024-11-15 09:47:28 +01:00
|
|
|
bundleUrl = [NSURL URLWithString:@"https://github.com/revenge-mod/revenge-bundle/releases/latest/download/revenge.min.js"];
|
2024-11-15 11:45:12 +01:00
|
|
|
RevengeLog(@"Using default bundle URL: %@", bundleUrl.absoluteString);
|
2024-11-14 11:15:18 +01:00
|
|
|
}
|
|
|
|
|
|
2024-11-15 09:47:28 +01:00
|
|
|
NSMutableURLRequest *bundleRequest = [NSMutableURLRequest requestWithURL:bundleUrl
|
|
|
|
|
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
|
2024-11-14 11:15:18 +01:00
|
|
|
timeoutInterval:3.0];
|
|
|
|
|
|
2024-11-15 09:47:28 +01:00
|
|
|
NSString *bundleEtag = [NSString stringWithContentsOfURL:[pyoncordDirectory URLByAppendingPathComponent:@"etag.txt"]
|
|
|
|
|
encoding:NSUTF8StringEncoding
|
2024-11-14 11:15:18 +01:00
|
|
|
error:nil];
|
|
|
|
|
if (bundleEtag && bundle) {
|
|
|
|
|
[bundleRequest setValue:bundleEtag forHTTPHeaderField:@"If-None-Match"];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
|
|
|
|
|
[[session dataTaskWithRequest:bundleRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
|
|
|
|
|
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
|
|
|
|
|
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
|
|
|
|
|
if (httpResponse.statusCode == 200) {
|
|
|
|
|
bundle = data;
|
|
|
|
|
[bundle writeToURL:[pyoncordDirectory URLByAppendingPathComponent:@"bundle.js"] atomically:YES];
|
2024-11-15 09:47:28 +01:00
|
|
|
|
2024-11-14 11:15:18 +01:00
|
|
|
NSString *etag = [httpResponse.allHeaderFields objectForKey:@"Etag"];
|
|
|
|
|
if (etag) {
|
2024-11-15 09:47:28 +01:00
|
|
|
[etag writeToURL:[pyoncordDirectory URLByAppendingPathComponent:@"etag.txt"]
|
|
|
|
|
atomically:YES
|
|
|
|
|
encoding:NSUTF8StringEncoding
|
2024-11-14 11:15:18 +01:00
|
|
|
error:nil];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
dispatch_group_leave(group);
|
|
|
|
|
}] resume];
|
|
|
|
|
|
|
|
|
|
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
|
|
|
|
|
|
|
|
|
|
NSString *themeString = [NSString stringWithContentsOfURL:[pyoncordDirectory URLByAppendingPathComponent:@"current-theme.json"]
|
|
|
|
|
encoding:NSUTF8StringEncoding
|
|
|
|
|
error:nil];
|
|
|
|
|
if (themeString) {
|
|
|
|
|
NSString *jsCode = [NSString stringWithFormat:@"globalThis.__PYON_LOADER__.storedTheme=%@", themeString];
|
fix: replace speculative Bridgeless hook with RainTweak's verified approach
The RCTInstance/-_loadScriptFromSource: + fake-RCTSource hook from the
previous commit was a plausible guess from RN's public source, but
codeberg.org/raincord/RainTweak - an actively-shipping loader for a sibling
Revenge/Bunny fork - proves both the Bridgeless diagnosis correct (its %ctor
refuses to run below Discord v332, i.e. pre-Bridgeless) and shows a cleaner,
verified mechanism: hook RCTHost/-instance:didInitializeRuntime:, let
Discord's own bundle load untouched via %orig, then evaluate Revenge's
scripts directly against the live JSI runtime instead of faking another
bundle load.
- Add Headers/JSI.h + Sources/JSI.mm (ported from RainTweak's JSI.mm):
evaluates NSData as JS or Hermes bytecode directly against a
facebook::jsi::Runtime.
- Add Headers/RCTHost.h declaring the hook target's signature (RN ships no
public header for this internal class).
- Vendor Headers/jsi/{jsi.h,jsi-inl.h,instrumentation.h} - Meta's MIT-licensed
JSI headers, which Theos doesn't provide; RainTweak vendors the same files.
- Rewrite Tweak.x -> Tweak.xm (needs C++ for jsi::Runtime&): runRevengeInjection
now takes a plain data/async execute callback, driven by either the new
RCTHost+JSI hook or the legacy RCTCxxBridge hook (kept as a no-cost
fallback), guarded by a didInject flag so only one path actually injects.
- Makefile: build .xm/.mm sources, add -std=c++17 CCFLAGS matching RainTweak.
Still unverified against a real device, but the mechanism itself is no longer
a guess - it's the one running in a comparable, currently-shipping mod.
2026-08-03 10:10:32 -04:00
|
|
|
execute([jsCode dataUsingEncoding:NSUTF8StringEncoding], async);
|
2024-11-14 11:15:18 +01:00
|
|
|
}
|
|
|
|
|
|
2024-11-14 22:50:08 +01:00
|
|
|
NSData *fontData = [NSData dataWithContentsOfURL:[pyoncordDirectory URLByAppendingPathComponent:@"fonts.json"]];
|
|
|
|
|
if (fontData) {
|
|
|
|
|
NSError *jsonError;
|
|
|
|
|
NSDictionary *fontDict = [NSJSONSerialization JSONObjectWithData:fontData options:0 error:&jsonError];
|
|
|
|
|
if (!jsonError && fontDict[@"main"]) {
|
2024-11-15 11:45:12 +01:00
|
|
|
RevengeLog(@"Found font configuration, applying...");
|
2024-11-14 22:50:08 +01:00
|
|
|
patchFonts(fontDict[@"main"], fontDict[@"name"]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-14 11:15:18 +01:00
|
|
|
if (bundle) {
|
2024-11-15 11:45:12 +01:00
|
|
|
RevengeLog(@"Executing JS bundle");
|
fix: replace speculative Bridgeless hook with RainTweak's verified approach
The RCTInstance/-_loadScriptFromSource: + fake-RCTSource hook from the
previous commit was a plausible guess from RN's public source, but
codeberg.org/raincord/RainTweak - an actively-shipping loader for a sibling
Revenge/Bunny fork - proves both the Bridgeless diagnosis correct (its %ctor
refuses to run below Discord v332, i.e. pre-Bridgeless) and shows a cleaner,
verified mechanism: hook RCTHost/-instance:didInitializeRuntime:, let
Discord's own bundle load untouched via %orig, then evaluate Revenge's
scripts directly against the live JSI runtime instead of faking another
bundle load.
- Add Headers/JSI.h + Sources/JSI.mm (ported from RainTweak's JSI.mm):
evaluates NSData as JS or Hermes bytecode directly against a
facebook::jsi::Runtime.
- Add Headers/RCTHost.h declaring the hook target's signature (RN ships no
public header for this internal class).
- Vendor Headers/jsi/{jsi.h,jsi-inl.h,instrumentation.h} - Meta's MIT-licensed
JSI headers, which Theos doesn't provide; RainTweak vendors the same files.
- Rewrite Tweak.x -> Tweak.xm (needs C++ for jsi::Runtime&): runRevengeInjection
now takes a plain data/async execute callback, driven by either the new
RCTHost+JSI hook or the legacy RCTCxxBridge hook (kept as a no-cost
fallback), guarded by a didInject flag so only one path actually injects.
- Makefile: build .xm/.mm sources, add -std=c++17 CCFLAGS matching RainTweak.
Still unverified against a real device, but the mechanism itself is no longer
a guess - it's the one running in a comparable, currently-shipping mod.
2026-08-03 10:10:32 -04:00
|
|
|
execute(bundle, async);
|
2024-11-14 11:15:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NSURL *preloadsDirectory = [pyoncordDirectory URLByAppendingPathComponent:@"preloads"];
|
|
|
|
|
if ([[NSFileManager defaultManager] fileExistsAtPath:preloadsDirectory.path]) {
|
|
|
|
|
NSError *error = nil;
|
|
|
|
|
NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:preloadsDirectory
|
|
|
|
|
includingPropertiesForKeys:nil
|
|
|
|
|
options:0
|
|
|
|
|
error:&error];
|
|
|
|
|
if (!error) {
|
|
|
|
|
for (NSURL *fileURL in contents) {
|
|
|
|
|
if ([[fileURL pathExtension] isEqualToString:@"js"]) {
|
2024-11-15 11:45:12 +01:00
|
|
|
RevengeLog(@"Executing preload JS file %@", fileURL.absoluteString);
|
2024-11-14 11:15:18 +01:00
|
|
|
NSData *data = [NSData dataWithContentsOfURL:fileURL];
|
|
|
|
|
if (data) {
|
fix: replace speculative Bridgeless hook with RainTweak's verified approach
The RCTInstance/-_loadScriptFromSource: + fake-RCTSource hook from the
previous commit was a plausible guess from RN's public source, but
codeberg.org/raincord/RainTweak - an actively-shipping loader for a sibling
Revenge/Bunny fork - proves both the Bridgeless diagnosis correct (its %ctor
refuses to run below Discord v332, i.e. pre-Bridgeless) and shows a cleaner,
verified mechanism: hook RCTHost/-instance:didInitializeRuntime:, let
Discord's own bundle load untouched via %orig, then evaluate Revenge's
scripts directly against the live JSI runtime instead of faking another
bundle load.
- Add Headers/JSI.h + Sources/JSI.mm (ported from RainTweak's JSI.mm):
evaluates NSData as JS or Hermes bytecode directly against a
facebook::jsi::Runtime.
- Add Headers/RCTHost.h declaring the hook target's signature (RN ships no
public header for this internal class).
- Vendor Headers/jsi/{jsi.h,jsi-inl.h,instrumentation.h} - Meta's MIT-licensed
JSI headers, which Theos doesn't provide; RainTweak vendors the same files.
- Rewrite Tweak.x -> Tweak.xm (needs C++ for jsi::Runtime&): runRevengeInjection
now takes a plain data/async execute callback, driven by either the new
RCTHost+JSI hook or the legacy RCTCxxBridge hook (kept as a no-cost
fallback), guarded by a didInject flag so only one path actually injects.
- Makefile: build .xm/.mm sources, add -std=c++17 CCFLAGS matching RainTweak.
Still unverified against a real device, but the mechanism itself is no longer
a guess - it's the one running in a comparable, currently-shipping mod.
2026-08-03 10:10:32 -04:00
|
|
|
execute(data, async);
|
2024-11-14 11:15:18 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2024-11-15 11:45:12 +01:00
|
|
|
RevengeLog(@"Error reading contents of preloads directory");
|
2024-11-14 11:15:18 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-03 09:46:46 -04:00
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
|
fix: replace speculative Bridgeless hook with RainTweak's verified approach
The RCTInstance/-_loadScriptFromSource: + fake-RCTSource hook from the
previous commit was a plausible guess from RN's public source, but
codeberg.org/raincord/RainTweak - an actively-shipping loader for a sibling
Revenge/Bunny fork - proves both the Bridgeless diagnosis correct (its %ctor
refuses to run below Discord v332, i.e. pre-Bridgeless) and shows a cleaner,
verified mechanism: hook RCTHost/-instance:didInitializeRuntime:, let
Discord's own bundle load untouched via %orig, then evaluate Revenge's
scripts directly against the live JSI runtime instead of faking another
bundle load.
- Add Headers/JSI.h + Sources/JSI.mm (ported from RainTweak's JSI.mm):
evaluates NSData as JS or Hermes bytecode directly against a
facebook::jsi::Runtime.
- Add Headers/RCTHost.h declaring the hook target's signature (RN ships no
public header for this internal class).
- Vendor Headers/jsi/{jsi.h,jsi-inl.h,instrumentation.h} - Meta's MIT-licensed
JSI headers, which Theos doesn't provide; RainTweak vendors the same files.
- Rewrite Tweak.x -> Tweak.xm (needs C++ for jsi::Runtime&): runRevengeInjection
now takes a plain data/async execute callback, driven by either the new
RCTHost+JSI hook or the legacy RCTCxxBridge hook (kept as a no-cost
fallback), guarded by a didInject flag so only one path actually injects.
- Makefile: build .xm/.mm sources, add -std=c++17 CCFLAGS matching RainTweak.
Still unverified against a real device, but the mechanism itself is no longer
a guess - it's the one running in a comparable, currently-shipping mod.
2026-08-03 10:10:32 -04:00
|
|
|
%hook RCTHost
|
2026-08-03 09:46:46 -04:00
|
|
|
|
fix: replace speculative Bridgeless hook with RainTweak's verified approach
The RCTInstance/-_loadScriptFromSource: + fake-RCTSource hook from the
previous commit was a plausible guess from RN's public source, but
codeberg.org/raincord/RainTweak - an actively-shipping loader for a sibling
Revenge/Bunny fork - proves both the Bridgeless diagnosis correct (its %ctor
refuses to run below Discord v332, i.e. pre-Bridgeless) and shows a cleaner,
verified mechanism: hook RCTHost/-instance:didInitializeRuntime:, let
Discord's own bundle load untouched via %orig, then evaluate Revenge's
scripts directly against the live JSI runtime instead of faking another
bundle load.
- Add Headers/JSI.h + Sources/JSI.mm (ported from RainTweak's JSI.mm):
evaluates NSData as JS or Hermes bytecode directly against a
facebook::jsi::Runtime.
- Add Headers/RCTHost.h declaring the hook target's signature (RN ships no
public header for this internal class).
- Vendor Headers/jsi/{jsi.h,jsi-inl.h,instrumentation.h} - Meta's MIT-licensed
JSI headers, which Theos doesn't provide; RainTweak vendors the same files.
- Rewrite Tweak.x -> Tweak.xm (needs C++ for jsi::Runtime&): runRevengeInjection
now takes a plain data/async execute callback, driven by either the new
RCTHost+JSI hook or the legacy RCTCxxBridge hook (kept as a no-cost
fallback), guarded by a didInject flag so only one path actually injects.
- Makefile: build .xm/.mm sources, add -std=c++17 CCFLAGS matching RainTweak.
Still unverified against a real device, but the mechanism itself is no longer
a guess - it's the one running in a comparable, currently-shipping mod.
2026-08-03 10:10:32 -04:00
|
|
|
/**
|
|
|
|
|
* Bridgeless-mode entry point (React Native's New Architecture) - fires once the JS runtime is
|
|
|
|
|
* ready, letting Discord's own bundle load completely untouched via %orig first. Revenge's own
|
|
|
|
|
* scripts are then evaluated directly against the same runtime via JSI, rather than trying to
|
|
|
|
|
* masquerade as another RCTSource bundle load (which has no public constructor). This mirrors
|
|
|
|
|
* RainTweak's verified approach - see comment on `runRevengeInjection` above.
|
|
|
|
|
*/
|
|
|
|
|
- (void)instance:(id)instance didInitializeRuntime:(jsi::Runtime &)runtime {
|
|
|
|
|
%orig;
|
2026-08-03 09:46:46 -04:00
|
|
|
|
fix: replace speculative Bridgeless hook with RainTweak's verified approach
The RCTInstance/-_loadScriptFromSource: + fake-RCTSource hook from the
previous commit was a plausible guess from RN's public source, but
codeberg.org/raincord/RainTweak - an actively-shipping loader for a sibling
Revenge/Bunny fork - proves both the Bridgeless diagnosis correct (its %ctor
refuses to run below Discord v332, i.e. pre-Bridgeless) and shows a cleaner,
verified mechanism: hook RCTHost/-instance:didInitializeRuntime:, let
Discord's own bundle load untouched via %orig, then evaluate Revenge's
scripts directly against the live JSI runtime instead of faking another
bundle load.
- Add Headers/JSI.h + Sources/JSI.mm (ported from RainTweak's JSI.mm):
evaluates NSData as JS or Hermes bytecode directly against a
facebook::jsi::Runtime.
- Add Headers/RCTHost.h declaring the hook target's signature (RN ships no
public header for this internal class).
- Vendor Headers/jsi/{jsi.h,jsi-inl.h,instrumentation.h} - Meta's MIT-licensed
JSI headers, which Theos doesn't provide; RainTweak vendors the same files.
- Rewrite Tweak.x -> Tweak.xm (needs C++ for jsi::Runtime&): runRevengeInjection
now takes a plain data/async execute callback, driven by either the new
RCTHost+JSI hook or the legacy RCTCxxBridge hook (kept as a no-cost
fallback), guarded by a didInject flag so only one path actually injects.
- Makefile: build .xm/.mm sources, add -std=c++17 CCFLAGS matching RainTweak.
Still unverified against a real device, but the mechanism itself is no longer
a guess - it's the one running in a comparable, currently-shipping mod.
2026-08-03 10:10:32 -04:00
|
|
|
if (didInject) return;
|
|
|
|
|
didInject = YES;
|
2026-08-03 09:46:46 -04:00
|
|
|
|
fix: replace speculative Bridgeless hook with RainTweak's verified approach
The RCTInstance/-_loadScriptFromSource: + fake-RCTSource hook from the
previous commit was a plausible guess from RN's public source, but
codeberg.org/raincord/RainTweak - an actively-shipping loader for a sibling
Revenge/Bunny fork - proves both the Bridgeless diagnosis correct (its %ctor
refuses to run below Discord v332, i.e. pre-Bridgeless) and shows a cleaner,
verified mechanism: hook RCTHost/-instance:didInitializeRuntime:, let
Discord's own bundle load untouched via %orig, then evaluate Revenge's
scripts directly against the live JSI runtime instead of faking another
bundle load.
- Add Headers/JSI.h + Sources/JSI.mm (ported from RainTweak's JSI.mm):
evaluates NSData as JS or Hermes bytecode directly against a
facebook::jsi::Runtime.
- Add Headers/RCTHost.h declaring the hook target's signature (RN ships no
public header for this internal class).
- Vendor Headers/jsi/{jsi.h,jsi-inl.h,instrumentation.h} - Meta's MIT-licensed
JSI headers, which Theos doesn't provide; RainTweak vendors the same files.
- Rewrite Tweak.x -> Tweak.xm (needs C++ for jsi::Runtime&): runRevengeInjection
now takes a plain data/async execute callback, driven by either the new
RCTHost+JSI hook or the legacy RCTCxxBridge hook (kept as a no-cost
fallback), guarded by a didInject flag so only one path actually injects.
- Makefile: build .xm/.mm sources, add -std=c++17 CCFLAGS matching RainTweak.
Still unverified against a real device, but the mechanism itself is no longer
a guess - it's the one running in a comparable, currently-shipping mod.
2026-08-03 10:10:32 -04:00
|
|
|
runRevengeInjection(YES, ^(NSData *data, BOOL async) {
|
|
|
|
|
[JSI evaluate:data tag:@"revenge" runtime:runtime];
|
|
|
|
|
});
|
2024-11-14 11:15:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
%end
|
|
|
|
|
|
fix: replace speculative Bridgeless hook with RainTweak's verified approach
The RCTInstance/-_loadScriptFromSource: + fake-RCTSource hook from the
previous commit was a plausible guess from RN's public source, but
codeberg.org/raincord/RainTweak - an actively-shipping loader for a sibling
Revenge/Bunny fork - proves both the Bridgeless diagnosis correct (its %ctor
refuses to run below Discord v332, i.e. pre-Bridgeless) and shows a cleaner,
verified mechanism: hook RCTHost/-instance:didInitializeRuntime:, let
Discord's own bundle load untouched via %orig, then evaluate Revenge's
scripts directly against the live JSI runtime instead of faking another
bundle load.
- Add Headers/JSI.h + Sources/JSI.mm (ported from RainTweak's JSI.mm):
evaluates NSData as JS or Hermes bytecode directly against a
facebook::jsi::Runtime.
- Add Headers/RCTHost.h declaring the hook target's signature (RN ships no
public header for this internal class).
- Vendor Headers/jsi/{jsi.h,jsi-inl.h,instrumentation.h} - Meta's MIT-licensed
JSI headers, which Theos doesn't provide; RainTweak vendors the same files.
- Rewrite Tweak.x -> Tweak.xm (needs C++ for jsi::Runtime&): runRevengeInjection
now takes a plain data/async execute callback, driven by either the new
RCTHost+JSI hook or the legacy RCTCxxBridge hook (kept as a no-cost
fallback), guarded by a didInject flag so only one path actually injects.
- Makefile: build .xm/.mm sources, add -std=c++17 CCFLAGS matching RainTweak.
Still unverified against a real device, but the mechanism itself is no longer
a guess - it's the one running in a comparable, currently-shipping mod.
2026-08-03 10:10:32 -04:00
|
|
|
%hook RCTCxxBridge
|
2026-08-03 09:46:46 -04:00
|
|
|
|
fix: replace speculative Bridgeless hook with RainTweak's verified approach
The RCTInstance/-_loadScriptFromSource: + fake-RCTSource hook from the
previous commit was a plausible guess from RN's public source, but
codeberg.org/raincord/RainTweak - an actively-shipping loader for a sibling
Revenge/Bunny fork - proves both the Bridgeless diagnosis correct (its %ctor
refuses to run below Discord v332, i.e. pre-Bridgeless) and shows a cleaner,
verified mechanism: hook RCTHost/-instance:didInitializeRuntime:, let
Discord's own bundle load untouched via %orig, then evaluate Revenge's
scripts directly against the live JSI runtime instead of faking another
bundle load.
- Add Headers/JSI.h + Sources/JSI.mm (ported from RainTweak's JSI.mm):
evaluates NSData as JS or Hermes bytecode directly against a
facebook::jsi::Runtime.
- Add Headers/RCTHost.h declaring the hook target's signature (RN ships no
public header for this internal class).
- Vendor Headers/jsi/{jsi.h,jsi-inl.h,instrumentation.h} - Meta's MIT-licensed
JSI headers, which Theos doesn't provide; RainTweak vendors the same files.
- Rewrite Tweak.x -> Tweak.xm (needs C++ for jsi::Runtime&): runRevengeInjection
now takes a plain data/async execute callback, driven by either the new
RCTHost+JSI hook or the legacy RCTCxxBridge hook (kept as a no-cost
fallback), guarded by a didInject flag so only one path actually injects.
- Makefile: build .xm/.mm sources, add -std=c++17 CCFLAGS matching RainTweak.
Still unverified against a real device, but the mechanism itself is no longer
a guess - it's the one running in a comparable, currently-shipping mod.
2026-08-03 10:10:32 -04:00
|
|
|
// Legacy-bridge entry point. Fires when the host app runs React Native's old (non-Bridgeless)
|
|
|
|
|
// bridge. Kept for hosts that haven't moved to Bridgeless; harmless if RCTCxxBridge is never
|
|
|
|
|
// instantiated (Logos skips hooking classes that aren't present at runtime).
|
|
|
|
|
- (void)executeApplicationScript:(NSData *)script url:(NSURL *)url async:(BOOL)async {
|
|
|
|
|
if (![url.absoluteString containsString:@"main.jsbundle"] || didInject) {
|
2026-08-03 09:46:46 -04:00
|
|
|
return %orig;
|
|
|
|
|
}
|
fix: replace speculative Bridgeless hook with RainTweak's verified approach
The RCTInstance/-_loadScriptFromSource: + fake-RCTSource hook from the
previous commit was a plausible guess from RN's public source, but
codeberg.org/raincord/RainTweak - an actively-shipping loader for a sibling
Revenge/Bunny fork - proves both the Bridgeless diagnosis correct (its %ctor
refuses to run below Discord v332, i.e. pre-Bridgeless) and shows a cleaner,
verified mechanism: hook RCTHost/-instance:didInitializeRuntime:, let
Discord's own bundle load untouched via %orig, then evaluate Revenge's
scripts directly against the live JSI runtime instead of faking another
bundle load.
- Add Headers/JSI.h + Sources/JSI.mm (ported from RainTweak's JSI.mm):
evaluates NSData as JS or Hermes bytecode directly against a
facebook::jsi::Runtime.
- Add Headers/RCTHost.h declaring the hook target's signature (RN ships no
public header for this internal class).
- Vendor Headers/jsi/{jsi.h,jsi-inl.h,instrumentation.h} - Meta's MIT-licensed
JSI headers, which Theos doesn't provide; RainTweak vendors the same files.
- Rewrite Tweak.x -> Tweak.xm (needs C++ for jsi::Runtime&): runRevengeInjection
now takes a plain data/async execute callback, driven by either the new
RCTHost+JSI hook or the legacy RCTCxxBridge hook (kept as a no-cost
fallback), guarded by a didInject flag so only one path actually injects.
- Makefile: build .xm/.mm sources, add -std=c++17 CCFLAGS matching RainTweak.
Still unverified against a real device, but the mechanism itself is no longer
a guess - it's the one running in a comparable, currently-shipping mod.
2026-08-03 10:10:32 -04:00
|
|
|
didInject = YES;
|
2026-08-03 09:46:46 -04:00
|
|
|
|
fix: replace speculative Bridgeless hook with RainTweak's verified approach
The RCTInstance/-_loadScriptFromSource: + fake-RCTSource hook from the
previous commit was a plausible guess from RN's public source, but
codeberg.org/raincord/RainTweak - an actively-shipping loader for a sibling
Revenge/Bunny fork - proves both the Bridgeless diagnosis correct (its %ctor
refuses to run below Discord v332, i.e. pre-Bridgeless) and shows a cleaner,
verified mechanism: hook RCTHost/-instance:didInitializeRuntime:, let
Discord's own bundle load untouched via %orig, then evaluate Revenge's
scripts directly against the live JSI runtime instead of faking another
bundle load.
- Add Headers/JSI.h + Sources/JSI.mm (ported from RainTweak's JSI.mm):
evaluates NSData as JS or Hermes bytecode directly against a
facebook::jsi::Runtime.
- Add Headers/RCTHost.h declaring the hook target's signature (RN ships no
public header for this internal class).
- Vendor Headers/jsi/{jsi.h,jsi-inl.h,instrumentation.h} - Meta's MIT-licensed
JSI headers, which Theos doesn't provide; RainTweak vendors the same files.
- Rewrite Tweak.x -> Tweak.xm (needs C++ for jsi::Runtime&): runRevengeInjection
now takes a plain data/async execute callback, driven by either the new
RCTHost+JSI hook or the legacy RCTCxxBridge hook (kept as a no-cost
fallback), guarded by a didInject flag so only one path actually injects.
- Makefile: build .xm/.mm sources, add -std=c++17 CCFLAGS matching RainTweak.
Still unverified against a real device, but the mechanism itself is no longer
a guess - it's the one running in a comparable, currently-shipping mod.
2026-08-03 10:10:32 -04:00
|
|
|
BOOL injected = runRevengeInjection(async, ^(NSData *data, BOOL scriptAsync) {
|
|
|
|
|
%orig(data, source, scriptAsync);
|
2026-08-03 09:46:46 -04:00
|
|
|
});
|
fix: replace speculative Bridgeless hook with RainTweak's verified approach
The RCTInstance/-_loadScriptFromSource: + fake-RCTSource hook from the
previous commit was a plausible guess from RN's public source, but
codeberg.org/raincord/RainTweak - an actively-shipping loader for a sibling
Revenge/Bunny fork - proves both the Bridgeless diagnosis correct (its %ctor
refuses to run below Discord v332, i.e. pre-Bridgeless) and shows a cleaner,
verified mechanism: hook RCTHost/-instance:didInitializeRuntime:, let
Discord's own bundle load untouched via %orig, then evaluate Revenge's
scripts directly against the live JSI runtime instead of faking another
bundle load.
- Add Headers/JSI.h + Sources/JSI.mm (ported from RainTweak's JSI.mm):
evaluates NSData as JS or Hermes bytecode directly against a
facebook::jsi::Runtime.
- Add Headers/RCTHost.h declaring the hook target's signature (RN ships no
public header for this internal class).
- Vendor Headers/jsi/{jsi.h,jsi-inl.h,instrumentation.h} - Meta's MIT-licensed
JSI headers, which Theos doesn't provide; RainTweak vendors the same files.
- Rewrite Tweak.x -> Tweak.xm (needs C++ for jsi::Runtime&): runRevengeInjection
now takes a plain data/async execute callback, driven by either the new
RCTHost+JSI hook or the legacy RCTCxxBridge hook (kept as a no-cost
fallback), guarded by a didInject flag so only one path actually injects.
- Makefile: build .xm/.mm sources, add -std=c++17 CCFLAGS matching RainTweak.
Still unverified against a real device, but the mechanism itself is no longer
a guess - it's the one running in a comparable, currently-shipping mod.
2026-08-03 10:10:32 -04:00
|
|
|
if (!injected) {
|
|
|
|
|
didInject = NO;
|
|
|
|
|
return %orig;
|
|
|
|
|
}
|
2026-08-03 09:46:46 -04:00
|
|
|
|
fix: replace speculative Bridgeless hook with RainTweak's verified approach
The RCTInstance/-_loadScriptFromSource: + fake-RCTSource hook from the
previous commit was a plausible guess from RN's public source, but
codeberg.org/raincord/RainTweak - an actively-shipping loader for a sibling
Revenge/Bunny fork - proves both the Bridgeless diagnosis correct (its %ctor
refuses to run below Discord v332, i.e. pre-Bridgeless) and shows a cleaner,
verified mechanism: hook RCTHost/-instance:didInitializeRuntime:, let
Discord's own bundle load untouched via %orig, then evaluate Revenge's
scripts directly against the live JSI runtime instead of faking another
bundle load.
- Add Headers/JSI.h + Sources/JSI.mm (ported from RainTweak's JSI.mm):
evaluates NSData as JS or Hermes bytecode directly against a
facebook::jsi::Runtime.
- Add Headers/RCTHost.h declaring the hook target's signature (RN ships no
public header for this internal class).
- Vendor Headers/jsi/{jsi.h,jsi-inl.h,instrumentation.h} - Meta's MIT-licensed
JSI headers, which Theos doesn't provide; RainTweak vendors the same files.
- Rewrite Tweak.x -> Tweak.xm (needs C++ for jsi::Runtime&): runRevengeInjection
now takes a plain data/async execute callback, driven by either the new
RCTHost+JSI hook or the legacy RCTCxxBridge hook (kept as a no-cost
fallback), guarded by a didInject flag so only one path actually injects.
- Makefile: build .xm/.mm sources, add -std=c++17 CCFLAGS matching RainTweak.
Still unverified against a real device, but the mechanism itself is no longer
a guess - it's the one running in a comparable, currently-shipping mod.
2026-08-03 10:10:32 -04:00
|
|
|
%orig(script, url, async);
|
2026-08-03 09:46:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
%end
|
|
|
|
|
|
2024-11-14 11:15:18 +01:00
|
|
|
%ctor {
|
2024-11-15 09:47:28 +01:00
|
|
|
@autoreleasepool {
|
2024-11-15 11:45:12 +01:00
|
|
|
source = [NSURL URLWithString:@"revenge"];
|
2024-11-15 09:47:28 +01:00
|
|
|
|
2024-11-14 11:15:18 +01:00
|
|
|
NSString *install_prefix = @"/var/jb";
|
|
|
|
|
isJailbroken = [[NSFileManager defaultManager] fileExistsAtPath:install_prefix];
|
2024-11-15 09:47:28 +01:00
|
|
|
|
2024-11-15 11:45:12 +01:00
|
|
|
NSString *bundlePath = [NSString stringWithFormat:@"%@/Library/Application Support/RevengeResources.bundle", install_prefix];
|
|
|
|
|
RevengeLog(@"Is jailbroken: %d", isJailbroken);
|
|
|
|
|
RevengeLog(@"Bundle path for jailbroken: %@", bundlePath);
|
2024-11-15 09:47:28 +01:00
|
|
|
|
2024-11-15 11:45:12 +01:00
|
|
|
NSString *jailedPath = [[NSBundle mainBundle].bundleURL.path stringByAppendingPathComponent:@"RevengeResources.bundle"];
|
|
|
|
|
RevengeLog(@"Bundle path for jailed: %@", jailedPath);
|
2024-11-15 09:47:28 +01:00
|
|
|
|
2024-11-15 11:45:12 +01:00
|
|
|
revengePatchesBundlePath = isJailbroken ? bundlePath : jailedPath;
|
|
|
|
|
RevengeLog(@"Selected bundle path: %@", revengePatchesBundlePath);
|
2024-11-15 09:47:28 +01:00
|
|
|
|
2024-11-15 11:45:12 +01:00
|
|
|
BOOL bundleExists = [[NSFileManager defaultManager] fileExistsAtPath:revengePatchesBundlePath];
|
|
|
|
|
RevengeLog(@"Bundle exists at path: %d", bundleExists);
|
2024-11-15 09:47:28 +01:00
|
|
|
|
2024-11-14 11:15:18 +01:00
|
|
|
NSError *error = nil;
|
2024-11-15 11:45:12 +01:00
|
|
|
NSArray *bundleContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:revengePatchesBundlePath error:&error];
|
2024-11-14 11:15:18 +01:00
|
|
|
if (error) {
|
2024-11-15 11:45:12 +01:00
|
|
|
RevengeLog(@"Error listing bundle contents: %@", error);
|
2024-11-14 11:15:18 +01:00
|
|
|
} else {
|
2024-11-15 11:45:12 +01:00
|
|
|
RevengeLog(@"Bundle contents: %@", bundleContents);
|
2024-11-14 11:15:18 +01:00
|
|
|
}
|
2024-11-15 09:47:28 +01:00
|
|
|
|
fix: replace speculative Bridgeless hook with RainTweak's verified approach
The RCTInstance/-_loadScriptFromSource: + fake-RCTSource hook from the
previous commit was a plausible guess from RN's public source, but
codeberg.org/raincord/RainTweak - an actively-shipping loader for a sibling
Revenge/Bunny fork - proves both the Bridgeless diagnosis correct (its %ctor
refuses to run below Discord v332, i.e. pre-Bridgeless) and shows a cleaner,
verified mechanism: hook RCTHost/-instance:didInitializeRuntime:, let
Discord's own bundle load untouched via %orig, then evaluate Revenge's
scripts directly against the live JSI runtime instead of faking another
bundle load.
- Add Headers/JSI.h + Sources/JSI.mm (ported from RainTweak's JSI.mm):
evaluates NSData as JS or Hermes bytecode directly against a
facebook::jsi::Runtime.
- Add Headers/RCTHost.h declaring the hook target's signature (RN ships no
public header for this internal class).
- Vendor Headers/jsi/{jsi.h,jsi-inl.h,instrumentation.h} - Meta's MIT-licensed
JSI headers, which Theos doesn't provide; RainTweak vendors the same files.
- Rewrite Tweak.x -> Tweak.xm (needs C++ for jsi::Runtime&): runRevengeInjection
now takes a plain data/async execute callback, driven by either the new
RCTHost+JSI hook or the legacy RCTCxxBridge hook (kept as a no-cost
fallback), guarded by a didInject flag so only one path actually injects.
- Makefile: build .xm/.mm sources, add -std=c++17 CCFLAGS matching RainTweak.
Still unverified against a real device, but the mechanism itself is no longer
a guess - it's the one running in a comparable, currently-shipping mod.
2026-08-03 10:10:32 -04:00
|
|
|
pyoncordDirectory = getPyoncordDirectory();
|
2024-11-14 11:15:18 +01:00
|
|
|
loaderConfig = [[LoaderConfig alloc] init];
|
2024-11-15 15:29:51 +01:00
|
|
|
[loaderConfig loadConfig];
|
fix: replace speculative Bridgeless hook with RainTweak's verified approach
The RCTInstance/-_loadScriptFromSource: + fake-RCTSource hook from the
previous commit was a plausible guess from RN's public source, but
codeberg.org/raincord/RainTweak - an actively-shipping loader for a sibling
Revenge/Bunny fork - proves both the Bridgeless diagnosis correct (its %ctor
refuses to run below Discord v332, i.e. pre-Bridgeless) and shows a cleaner,
verified mechanism: hook RCTHost/-instance:didInitializeRuntime:, let
Discord's own bundle load untouched via %orig, then evaluate Revenge's
scripts directly against the live JSI runtime instead of faking another
bundle load.
- Add Headers/JSI.h + Sources/JSI.mm (ported from RainTweak's JSI.mm):
evaluates NSData as JS or Hermes bytecode directly against a
facebook::jsi::Runtime.
- Add Headers/RCTHost.h declaring the hook target's signature (RN ships no
public header for this internal class).
- Vendor Headers/jsi/{jsi.h,jsi-inl.h,instrumentation.h} - Meta's MIT-licensed
JSI headers, which Theos doesn't provide; RainTweak vendors the same files.
- Rewrite Tweak.x -> Tweak.xm (needs C++ for jsi::Runtime&): runRevengeInjection
now takes a plain data/async execute callback, driven by either the new
RCTHost+JSI hook or the legacy RCTCxxBridge hook (kept as a no-cost
fallback), guarded by a didInject flag so only one path actually injects.
- Makefile: build .xm/.mm sources, add -std=c++17 CCFLAGS matching RainTweak.
Still unverified against a real device, but the mechanism itself is no longer
a guess - it's the one running in a comparable, currently-shipping mod.
2026-08-03 10:10:32 -04:00
|
|
|
|
2024-11-14 11:15:18 +01:00
|
|
|
%init;
|
|
|
|
|
}
|
2024-11-15 09:47:28 +01:00
|
|
|
}
|