Skip to content

Commit eb4b346

Browse files
committed
pp_ctl.c - handle objects in @inc a bit more gracefully
If an object doesn't have an INC hook then don't call it. Either simply stringify the ref (think overloads), OR, if it is a blessed coderef, then just execute it like it was an unblessed coderef. Also handle when an object is passed as the first argument of the array form of call. Previously this would throw an exception as the first argument on the stack when we call_method() would not be blessed. When this is the scenario we pass in the array as the third argument to the method.
1 parent 10ba1af commit eb4b346

File tree

4 files changed

+52
-13
lines changed

4 files changed

+52
-13
lines changed

pod/perldelta.pod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,11 @@ and New Warnings
210210

211211
=item *
212212

213+
L<Object with arguments in @INC does not support a hook method
214+
|perldiag/"Object with arguments in @INC does not support a hook method">
215+
216+
=item *
217+
213218
XXX L<message|perldiag/"message">
214219

215220
=back

pod/perldiag.pod

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4461,6 +4461,14 @@ and you mentioned a variable that starts with 0 that has more than one
44614461
digit. You probably want to remove the leading 0, or if the intent was
44624462
to express a variable name in octal you should convert to decimal.
44634463

4464+
=item Object with arguments in @INC does not support a hook method
4465+
4466+
(F) You pushed an array reference hook into C<@INC> which has an object
4467+
as the first argument, but the object doesn't support any known hooks.
4468+
Since you used the array form of creating a hook, you should have supplied
4469+
an object that supports either the C<INC> or C<INCDIR> methods. You
4470+
could also use a coderef instead of an object.
4471+
44644472
=item Octal number > 037777777777 non-portable
44654473

44664474
(W portable) The octal number you specified is larger than 2**32-1

pp_ctl.c

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4307,25 +4307,55 @@ S_require_file(pTHX_ SV *sv)
43074307
SvSetSV_nosteal(nsv,sv);
43084308
}
43094309

4310+
const char *method = NULL;
43104311
SV * inc_idx_sv = save_scalar(PL_incgv);
43114312
sv_setiv(inc_idx_sv,inc_idx);
4313+
if (sv_isobject(loader)) {
4314+
/* if it is an object and it has an INC method, then
4315+
* call the method.
4316+
*/
4317+
HV *pkg = SvSTASH(SvRV(loader));
4318+
GV * gv = gv_fetchmethod_pvn_flags(pkg, "INC", 3, 0);
4319+
if (gv && isGV(gv)) {
4320+
method = "INC";
4321+
}
4322+
/* But if we have no method, check if this is a
4323+
* coderef, if it is then we treat it as an
4324+
* unblessed coderef would be treated: we
4325+
* execute it. If it is some other and it is in
4326+
* an array ref wrapper, then really we don't
4327+
* know what to do with it, (why use the
4328+
* wrapper?) and we throw an exception to help
4329+
* debug. If it is not in a wrapper assume it
4330+
* has an overload and treat it as a string.
4331+
* Maybe in the future we can detect if it does
4332+
* have overloading and throw an error if not.
4333+
*/
4334+
if (!method) {
4335+
if (SvTYPE(SvRV(loader)) != SVt_PVCV) {
4336+
if (dirsv != loader)
4337+
croak("Object with arguments in @INC does not support a hook method");
4338+
else
4339+
goto treat_as_string;
4340+
}
4341+
}
4342+
}
43124343

43134344
ENTER_with_name("call_INC_hook");
43144345
SAVETMPS;
4315-
EXTEND(SP, 2);
4316-
4346+
EXTEND(SP, 2 + ((method && (loader != dirsv)) ? 1 : 0));
43174347
PUSHMARK(SP);
4318-
PUSHs(dirsv);
4348+
PUSHs(method ? loader : dirsv); /* always use the object for method calls */
43194349
PUSHs(nsv);
4350+
if (method && (loader != dirsv)) /* add the args array for method calls */
4351+
PUSHs(dirsv);
43204352
PUTBACK;
43214353
if (SvGMAGICAL(loader)) {
43224354
SV *l = sv_newmortal();
43234355
sv_setsv_nomg(l, loader);
43244356
loader = l;
43254357
}
4326-
const char *method = NULL;
4327-
if (sv_isobject(loader)) {
4328-
method = "INC";
4358+
if (method) {
43294359
count = call_method(method, G_LIST|G_EVAL);
43304360
} else {
43314361
count = call_sv(loader, G_LIST|G_EVAL);
@@ -4482,12 +4512,13 @@ S_require_file(pTHX_ SV *sv)
44824512
filter_sub = NULL;
44834513
}
44844514
}
4485-
else if (path_searchable) {
4515+
else
4516+
treat_as_string:
4517+
if (path_searchable) {
44864518
/* match against a plain @INC element (non-searchable
44874519
* paths are only matched against refs in @INC) */
44884520
const char *dir;
44894521
STRLEN dirlen;
4490-
44914522
if (SvOK(dirsv)) {
44924523
dir = SvPV_nomg_const(dirsv, dirlen);
44934524
} else {

t/op/require_errors.t

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,6 @@ like $@, qr/^Can't locate \Q$nonsearch\E at/,
348348
{ }, 'INCDIR works as expected');
349349
}
350350
{
351-
local $::TODO = "Pending object handling improvements";
352351
# as of 5.37.7
353352
fresh_perl_like(
354353
'@INC = ("a",bless({},"CB"),"e");'
@@ -357,7 +356,6 @@ like $@, qr/^Can't locate \Q$nonsearch\E at/,
357356
{ }, 'Objects with no INC or INCDIR method are stringified');
358357
}
359358
{
360-
local $::TODO = "Pending object handling improvements";
361359
# as of 5.37.7
362360
fresh_perl_like(
363361
'{package CB; use overload qw("")=>sub { "blorg"};} '
@@ -367,7 +365,6 @@ like $@, qr/^Can't locate \Q$nonsearch\E at/,
367365
{ }, 'Objects with overload and no INC or INCDIR method are stringified');
368366
}
369367
{
370-
local $::TODO = "Pending object handling improvments";
371368
# as of 5.37.7
372369
fresh_perl_like(
373370
'@INC = ("a",bless(sub { warn "blessed sub called" },"CB"),"e");'
@@ -376,7 +373,6 @@ like $@, qr/^Can't locate \Q$nonsearch\E at/,
376373
{ }, 'Blessed subs with no hook methods are executed');
377374
}
378375
{
379-
local $::TODO = "Pending better error messages (eval)";
380376
# as of 5.37.7
381377
fresh_perl_like(
382378
'@INC = ("a",bless(sub { die "blessed sub called" },"CB"),"e");'
@@ -394,7 +390,6 @@ like $@, qr/^Can't locate \Q$nonsearch\E at/,
394390
{ }, 'Blessed subs with methods call method and produce expected message');
395391
}
396392
{
397-
local $::TODO = "Pending object handling improvments";
398393
# as of 5.37.7
399394
fresh_perl_like(
400395
'@INC = ("a",[bless([],"CB"),1],"e");'

0 commit comments

Comments
 (0)