mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-07-06 11:08:30 +00:00
Rewrite webpack hooking code to add (untested) support for webpack 4. It's not perfect yet. We have to wait for a module to be required to actually get require. Will have to investigate poking at the state of React to try making it load a feature module or something.
This commit is contained in:
parent
6c77e2ca5c
commit
194f93414d
3 changed files with 120 additions and 35 deletions
|
@ -1,4 +1,9 @@
|
||||||
<div class="list-header">4.0.0-rc1.5<span>@eb1433f63b4667bf9010</span> <time datetime="2018-05-10">(2018-05-10)</time></div>
|
<div class="list-header">4.0.0-rc1.7<span>@498c1b079484a762958a</span> <time datetime="2018-05-18">(2018-05-18)</time></div>
|
||||||
|
<ul class="chat-menu-content menu-side-padding">
|
||||||
|
<li>Changed: Rewrite the webpack hooking code to add support for webpack 4.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="list-header">4.0.0-rc1.6<span>@3d53d461b59654a0ec14</span> <time datetime="2018-05-18">(2018-05-18)</time></div>
|
||||||
<ul class="chat-menu-content menu-side-padding">
|
<ul class="chat-menu-content menu-side-padding">
|
||||||
<li>Added: Basic support for rich video cards in chat.</li>
|
<li>Added: Basic support for rich video cards in chat.</li>
|
||||||
<li>Changed: Begin working towards a standard data model for chat lines.</li>
|
<li>Changed: Begin working towards a standard data model for chat lines.</li>
|
||||||
|
|
|
@ -100,7 +100,7 @@ class FrankerFaceZ extends Module {
|
||||||
FrankerFaceZ.Logger = Logger;
|
FrankerFaceZ.Logger = Logger;
|
||||||
|
|
||||||
const VER = FrankerFaceZ.version_info = {
|
const VER = FrankerFaceZ.version_info = {
|
||||||
major: 4, minor: 0, revision: 0, extra: '-rc1.6',
|
major: 4, minor: 0, revision: 0, extra: '-rc1.7',
|
||||||
build: __webpack_hash__,
|
build: __webpack_hash__,
|
||||||
toString: () =>
|
toString: () =>
|
||||||
`${VER.major}.${VER.minor}.${VER.revision}${VER.extra || ''}${DEBUG ? '-dev' : ''}`
|
`${VER.major}.${VER.minor}.${VER.revision}${VER.extra || ''}${DEBUG ? '-dev' : ''}`
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
import Module from 'utilities/module';
|
import Module from 'utilities/module';
|
||||||
import {has} from 'utilities/object';
|
import {has, once} from 'utilities/object';
|
||||||
|
|
||||||
|
|
||||||
let last_muncher = 0;
|
let last_muncher = 0;
|
||||||
|
@ -23,6 +23,8 @@ export default class WebMunch extends Module {
|
||||||
this._module_names = {};
|
this._module_names = {};
|
||||||
this._mod_cache = {};
|
this._mod_cache = {};
|
||||||
|
|
||||||
|
this.v4 = false;
|
||||||
|
|
||||||
this.hookLoader();
|
this.hookLoader();
|
||||||
this.hookRequire();
|
this.hookRequire();
|
||||||
}
|
}
|
||||||
|
@ -32,33 +34,54 @@ export default class WebMunch extends Module {
|
||||||
// Loaded Modules
|
// Loaded Modules
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|
||||||
hookLoader(attempts) {
|
hookLoader(attempts = 0) {
|
||||||
if ( this._original_loader )
|
if ( this._original_loader )
|
||||||
return this.log.warn('Attempted to call hookLoader twice.');
|
return this.log.warn('Attempted to call hookLoader twice.');
|
||||||
|
|
||||||
this._original_loader = window.webpackJsonp;
|
if ( ! window.webpackJsonp ) {
|
||||||
if ( ! this._original_loader ) {
|
|
||||||
if ( attempts > 500 )
|
if ( attempts > 500 )
|
||||||
return this.log.error("Unable to find webpack's loader after two minutes.");
|
return this.log.error("Unable to find webpack's loader after two minutes.");
|
||||||
|
|
||||||
return setTimeout(this.hookLoader.bind(this, (attempts||0) + 1), 250);
|
return setTimeout(this.hookLoader.bind(this, attempts + 1), 250);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( typeof window.webpackJsonp === 'function' ) {
|
||||||
|
// v3
|
||||||
|
this._original_loader = window.webpackJsonp;
|
||||||
|
try {
|
||||||
|
window.webpackJsonp = this.webpackJsonpv3.bind(this);
|
||||||
|
} catch(err) {
|
||||||
|
this.log.warn('Unable to wrap webpackJsonp due to write protection.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if ( Array.isArray(window.webpackJsonp) ) {
|
||||||
|
// v4
|
||||||
|
this.v4 = true;
|
||||||
|
this._original_loader = window.webpackJsonp.push;
|
||||||
|
|
||||||
|
// Wrap all existing modules in case any of them haven't been required yet.
|
||||||
|
for(const chunk of window.webpackJsonp)
|
||||||
|
if ( chunk && chunk[1] )
|
||||||
|
this.processModulesV4(chunk[1]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
window.webpackJsonp.push = this.webpackJsonpv4.bind(this);
|
||||||
|
} catch(err) {
|
||||||
|
this.log.warn('Unable to wrap webpackJsonp (v4) due to write protection.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this.log.error('webpackJsonp is of an unknown value. Unable to wrap.');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.log.info(`Found and wrapped webpack's loader after ${(attempts||0)*250}ms.`);
|
this.log.info(`Found and wrapped webpack's loader after ${(attempts||0)*250}ms.`);
|
||||||
|
|
||||||
try {
|
|
||||||
window.webpackJsonp = this.webpackJsonp.bind(this);
|
|
||||||
} catch(err) {
|
|
||||||
this.log.info('Unable to wrap webpackJsonp normally due to write-protection. Escalating.');
|
|
||||||
try {
|
|
||||||
Object.defineProperty(window, 'webpackJsonp', {value: this.webpackJsonp.bind(this)});
|
|
||||||
} catch(e2) {
|
|
||||||
this.log.info('Unable to wrap webpackJsonp at this time. Some functionality may be broken as a result.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
webpackJsonp(chunk_ids, modules) {
|
|
||||||
|
webpackJsonpv3(chunk_ids, modules) {
|
||||||
const names = chunk_ids.map(x => this._module_names[x] || x).join(', ');
|
const names = chunk_ids.map(x => this._module_names[x] || x).join(', ');
|
||||||
this.log.info(`Twitch Chunk Loaded: ${chunk_ids} (${names})`);
|
this.log.info(`Twitch Chunk Loaded: ${chunk_ids} (${names})`);
|
||||||
this.log.debug(`Modules: ${Object.keys(modules)}`);
|
this.log.debug(`Modules: ${Object.keys(modules)}`);
|
||||||
|
@ -71,6 +94,51 @@ export default class WebMunch extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
processModulesV4(modules) {
|
||||||
|
const t = this;
|
||||||
|
|
||||||
|
for(const mod_id in modules)
|
||||||
|
if ( has(modules, mod_id) ) {
|
||||||
|
const original_module = modules[mod_id];
|
||||||
|
modules[mod_id] = function(module, exports, require, ...args) {
|
||||||
|
if ( ! t._require && typeof require === 'function' ) {
|
||||||
|
t.log.info(`require() grabbed from invocation of module ${mod_id}`);
|
||||||
|
t._require = require;
|
||||||
|
if ( t._resolve_require ) {
|
||||||
|
try {
|
||||||
|
for(const fn of t._resolve_require)
|
||||||
|
fn(require);
|
||||||
|
} catch(err) {
|
||||||
|
t.log.error('An error occured running require callbacks.', err);
|
||||||
|
}
|
||||||
|
|
||||||
|
t._resolve_require = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return original_module.call(this, module, exports, require, ...args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
webpackJsonpv4(data) {
|
||||||
|
const chunk_ids = data[0],
|
||||||
|
modules = data[1],
|
||||||
|
names = Array.isArray(chunk_ids) && chunk_ids.map(x => this._module_names[x] || x).join(', ');
|
||||||
|
|
||||||
|
this.log.info(`Twitch Chunk Loaded: ${chunk_ids} (${names})`);
|
||||||
|
this.log.debug(`Modules: ${Object.keys(modules)}`);
|
||||||
|
|
||||||
|
if ( modules )
|
||||||
|
this.processModulesV4(modules);
|
||||||
|
|
||||||
|
const res = this._original_loader.apply(window.webpackJsonp, arguments); // eslint-disable-line prefer-rest-params
|
||||||
|
this.emit(':loaded', chunk_ids, names, modules);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
// Finding Modules
|
// Finding Modules
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
@ -137,26 +205,38 @@ export default class WebMunch extends Module {
|
||||||
if ( this._require )
|
if ( this._require )
|
||||||
return Promise.resolve(this._require);
|
return Promise.resolve(this._require);
|
||||||
|
|
||||||
return new Promise(resolve => {
|
return new Promise((resolve, reject) => {
|
||||||
const fn = this._original_loader || window.webpackJsonp;
|
const fn = this._original_loader;
|
||||||
if ( ! fn ) {
|
if ( ! fn ) {
|
||||||
if ( limit > 100 )
|
if ( limit > 500 )
|
||||||
throw new Error('unable to find webpackJsonp');
|
reject(new Error('unable to find webpackJsonp'));
|
||||||
|
|
||||||
return setTimeout(() => this.getRequire(limit++).then(resolve), 100);
|
return setTimeout(() => this.getRequire(limit++).then(resolve), 250);
|
||||||
}
|
}
|
||||||
|
|
||||||
const id = `${this._id}$${this._rid++}`;
|
if ( this.v4 ) {
|
||||||
fn(
|
// There's currently no good way to grab require from
|
||||||
[],
|
// webpack 4 due to its lazy loading, so we just wait
|
||||||
{
|
// and hope that a module is imported.
|
||||||
[id]: (module, exports, __webpack_require__) => {
|
if ( this._resolve_require )
|
||||||
resolve(this._require = __webpack_require__);
|
this._resolve_require.push(resolve);
|
||||||
}
|
else
|
||||||
},
|
this._resolve_require = [resolve];
|
||||||
[id]
|
|
||||||
)
|
} else {
|
||||||
});
|
// Inject a fake module and use that to grab require.
|
||||||
|
const id = `${this._id}$${this._rid++}`;
|
||||||
|
fn(
|
||||||
|
[],
|
||||||
|
{
|
||||||
|
[id]: (module, exports, __webpack_require__) => {
|
||||||
|
resolve(this._require = __webpack_require__);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[id]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async hookRequire() {
|
async hookRequire() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue