tapable
tapable copied to clipboard
problem about tap method of interceptor
recently i try to use interceptor of tapable, in the Interception section of readme:
tap: (tap: Tap) => void Adding tap to your interceptor will trigger when a plugin taps into a hook. Provided is the Tap object. Tap object can't be changed.
it means if i use a intecptor of tap method, when a plugin taps into a hook, the corresponding function will be invoked. However, the following code snippet does not work as expected.
code snippet:
const { SyncBailHook } = require('tapable')
const hook = new SyncBailHook(['name'])
hook.intercept({
tap:(tapInfo) => {
console.log(tapInfo)
}
})
hook.tap('1', function (name) {
console.log(name, '1')
})
hook.tap('2', function (name) {
console.log(name, '2')
return 'wrong'
})
hook.tap('1', function (name) {
console.log(name, '2')
})
tap of interceptor only be called when it execute hook.call('webpack')
.
version of tapable: 1.1.0
It seems like hook.register
would work in your situation.
hook.intercept({
register:(tapInfo) => {
console.log(tapInfo)
}
})
Based on the documentation, I would have expected tap
and register
to fire at the same time.
I looked through the code. When a hook is triggered, interceptor.call
and interceptor.tap
are both called. It seems the only difference is that interceptor.call
is called with the arguments
that you used when calling your hook, and interceptor.tap
is called with the Tapable
object.
For example:
const { SyncHook } = require("tapable");
const greetingHook = new SyncHook(["name"]);
greetingHook.intercept({
register: (tapInfo) => {
console.log("πΎ new tap was registered", tapInfo);
},
call: (name) => {
console.log("π tapped method was called", name);
},
tap: (tapInfo) => {
console.log("π tapped method was called", tapInfo);
}
});
greetingHook.tap("EmailPlugin", function (name) {
console.log("Hi, this is an email for " + name);
});
// πΎ new tap was registered { type: "sync", fn: [Function], name: "EmailPlugin" }
greetingHook("Anthony");
// π tapped method was called Anthony
// π tapped method was called { type: "sync", fn: [Function], name: "EmailPlugin" }
@ooflorent Is this correct? If so, I could update the docs to make this more clear.
I looked through the code. When a hook is triggered,
interceptor.call
andinterceptor.tap
are both called. It seems the only difference is thatinterceptor.call
is called with thearguments
that you used when calling your hook, andinterceptor.tap
is called with theTapable
object.For example:
const { SyncHook } = require("tapable"); const greetingHook = new SyncHook(["name"]); greetingHook.intercept({ register: (tapInfo) => { console.log("πΎ new tap was registered", tapInfo); }, call: (name) => { console.log("π tapped method was called", name); }, tap: (tapInfo) => { console.log("π tapped method was called", tapInfo); } }); greetingHook.tap("EmailPlugin", function (name) { console.log("Hi, this is an email for " + name); }); // πΎ new tap was registered { type: "sync", fn: [Function], name: "EmailPlugin" } greetingHook("Anthony"); // π tapped method was called Anthony // π tapped method was called { type: "sync", fn: [Function], name: "EmailPlugin" }
@ooflorent Is this correct? If so, I could update the docs to make this more clear.
thanks for your replyοΌfrom the implementation of tapable, what u described is true. And what makes me confused are the docs.
when the developer use intercept
api , the interceptor
will be saved as the last element of interceptors which is a property of hook object. And when the developer call the hook, tapable will generate function string according to the context, then return function with new Function
api, and cached the function at the same time.
const { SyncHook } = require("tapable");
const greetingHook = new SyncHook(["name"]);
greetingHook.intercept({
register: (tapInfo) => {
console.log("πΎ new tap was registered", tapInfo);
},
call: (name) => {
console.log("π tapped method was called", name);
},
tap: (tapInfo) => {
console.log("π tapped method was called", tapInfo);
}
});
greetingHook.tap("EmailPlugin", function (name) {
console.log("Hi, this is an email for " + name);
});
// greetingHook("Anthony"); should use call instead of call it directly
greetingHook.call("Anthony");
these code will generate the function as follow.
function anonymous(name /*``*/ ) {
"use strict";
var _context;
var _x = this._x;
var _taps = this.taps;
var _interceptors = this.interceptors;
_interceptors[0].call(name);
var _tap0 = _taps[0];
_interceptors[0].tap(_tap0);
var _fn0 = _x[0];
_fn0(name);
}
from the generatored anonymous function, we can see that interceptor.call
and interceptor.tap
will be invoked when invoking of the anonymous which is referred as greetingHook.call
. And the difference is that nterceptor.call
will be trigger with the arguments, interceptor.tap
will be invoked with the tapInfo
. The invoking of interceptor.register
happened at tap
(Hook.js loc:32), in the function of tap
, it invokes _runRegisterInterceptors
(Hook.js loc:71), at this phase, developer can access the tapInfo and make some change to the tapInfo, the detail of _runRegisterInterceptors
is as follow:
_runRegisterInterceptors(options) {
for (const interceptor of this.interceptors) {
if (interceptor.register) {
const newOptions = interceptor.register(options);
if (newOptions !== undefined) options = newOptions;
}
}
return options;
}
Last but not least, i really really want the official team can improve the quality of this doc π π π. I am willing to make some efforts to improve the doc.
I looked through the code. When a hook is triggered,
interceptor.call
andinterceptor.tap
are both called. It seems the only difference is thatinterceptor.call
is called with thearguments
that you used when calling your hook, andinterceptor.tap
is called with theTapable
object.For example:
const { SyncHook } = require("tapable"); const greetingHook = new SyncHook(["name"]); greetingHook.intercept({ register: (tapInfo) => { console.log("πΎ new tap was registered", tapInfo); }, call: (name) => { console.log("π tapped method was called", name); }, tap: (tapInfo) => { console.log("π tapped method was called", tapInfo); } }); greetingHook.tap("EmailPlugin", function (name) { console.log("Hi, this is an email for " + name); }); // πΎ new tap was registered { type: "sync", fn: [Function], name: "EmailPlugin" } greetingHook("Anthony"); // π tapped method was called Anthony // π tapped method was called { type: "sync", fn: [Function], name: "EmailPlugin" }
@ooflorent Is this correct? If so, I could update the docs to make this more clear.
first thanks for your reply, i am agree with what you described above. Tapable
will generate function until you trigger the hookγthe example you mentioned will generate a anonymous function like so:
function anonymous(name /*``*/ ) {
"use strict";
var _context;
var _x = this._x;
var _taps = this.taps;
var _interceptors = this.interceptors;
_interceptors[0].call(name);
var _tap0 = _taps[0];
_interceptors[0].tap(_tap0);
var _fn0 = _x[0];
_fn0(name);
}
from the anonymous generated above, we can see that the interceptor.call
and interceptor.tap
will be invoked when the hook be triggered, the difference is that interceptor.call
accept the arguments, interceptor.tap
accept tapInfo objectγ The invoke of interceptor.register
in the lib/Hook.js
(loc:41), implementation of _runRegisterInterceptors
as follows οΌ
_runRegisterInterceptors(options) {
for (const interceptor of this.interceptors) {
if (interceptor.register) {
const newOptions = interceptor.register(options);
if (newOptions !== undefined) options = newOptions;
}
}
return options;
}
so when developer trigger the function
, the interceptor.register
will be invoked.
In summary, what you described is right absolutely. Last but not least, i really really want the official team can improve the quality of the doc, and i'm willing to contribute the doc if any need.