From d42a873f6b8b26a40c1b009de577bc31feb15394 Mon Sep 17 00:00:00 2001 From: gregor herrmann Date: Wed, 20 Sep 2023 21:39:15 +0200 Subject: New upstream version 0.66 --- .editorconfig | 4 ++ Changes | 10 ++++ MANIFEST | 2 + META.json | 12 ++-- META.yml | 12 ++-- hax/perl-additions.c.inc | 9 +-- hax/perl-backcompat.c.inc | 36 +++++++++--- lib/Future/AsyncAwait.pm | 35 ++++++++---- lib/Future/AsyncAwait.xs | 1 + lib/Future/AsyncAwait/Awaitable.pm | 2 +- lib/Future/AsyncAwait/ExtensionBuilder.pm | 4 +- lib/Future/AsyncAwait/ExtensionBuilder_data.pm.PL | 2 +- lib/Test/Future/AsyncAwait/Awaitable.pm | 2 +- t/01async-immediate.t | 9 +++ t/70await+feature-class.t | 70 +++++++++++++++++++++++ t/80async-method.t | 8 +-- t/81async-method+dynamically.t | 6 +- 17 files changed, 176 insertions(+), 48 deletions(-) create mode 100644 .editorconfig create mode 100644 t/70await+feature-class.t diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..24b6e3b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +root = true + +[*.{pm,pl,t}] +indent_size = 3 diff --git a/Changes b/Changes index 0add03d..8e09209 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,15 @@ Revision history for Future-AsyncAwait +0.66 2023-09-08 + [CHANGES] + * Add a unit test to check that `async method` works on core perl + class syntax + * Remember to implement `sub unimport` so that `no Future::AsyncAwait` + works + + [BUGFIXES] + * Provide a permit_hintkey to keep XPS happy + 0.65 2023-03-17 [CHANGES] * More specific unit-testing of the croak location when testing diff --git a/MANIFEST b/MANIFEST index ccf258a..7451b7c 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,3 +1,4 @@ +.editorconfig Build.PL Changes hax/cv_copy_flags.c.inc @@ -56,6 +57,7 @@ t/45sub-signatures.t t/50future-subclass.t t/51awaitable-role.t t/52awaitable-future.t +t/70await+feature-class.t t/70await+feature-try.t t/80async-method.t t/80async-multi-sub.t diff --git a/META.json b/META.json index c5e31f2..2c012e2 100644 --- a/META.json +++ b/META.json @@ -4,7 +4,7 @@ "Paul Evans " ], "dynamic_config" : 1, - "generated_by" : "Module::Build version 0.4231", + "generated_by" : "Module::Build version 0.4234", "license" : [ "perl_5" ], @@ -44,19 +44,19 @@ "provides" : { "Future::AsyncAwait" : { "file" : "lib/Future/AsyncAwait.pm", - "version" : "0.65" + "version" : "0.66" }, "Future::AsyncAwait::Awaitable" : { "file" : "lib/Future/AsyncAwait/Awaitable.pm", - "version" : "0.65" + "version" : "0.66" }, "Future::AsyncAwait::ExtensionBuilder" : { "file" : "lib/Future/AsyncAwait/ExtensionBuilder.pm", - "version" : "0.65" + "version" : "0.66" }, "Test::Future::AsyncAwait::Awaitable" : { "file" : "lib/Test/Future/AsyncAwait/Awaitable.pm", - "version" : "0.65" + "version" : "0.66" } }, "release_status" : "stable", @@ -66,6 +66,6 @@ ], "x_IRC" : "irc://irc.perl.org/#io-async" }, - "version" : "0.65", + "version" : "0.66", "x_serialization_backend" : "JSON::PP version 4.07" } diff --git a/META.yml b/META.yml index 2500113..c844700 100644 --- a/META.yml +++ b/META.yml @@ -11,7 +11,7 @@ configure_requires: XS::Parse::Keyword::Builder: '0.13' XS::Parse::Sublike::Builder: '0.14' dynamic_config: 1 -generated_by: 'Module::Build version 0.4231, CPAN::Meta::Converter version 2.150010' +generated_by: 'Module::Build version 0.4234, CPAN::Meta::Converter version 2.150010' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html @@ -20,16 +20,16 @@ name: Future-AsyncAwait provides: Future::AsyncAwait: file: lib/Future/AsyncAwait.pm - version: '0.65' + version: '0.66' Future::AsyncAwait::Awaitable: file: lib/Future/AsyncAwait/Awaitable.pm - version: '0.65' + version: '0.66' Future::AsyncAwait::ExtensionBuilder: file: lib/Future/AsyncAwait/ExtensionBuilder.pm - version: '0.65' + version: '0.66' Test::Future::AsyncAwait::Awaitable: file: lib/Test/Future/AsyncAwait/Awaitable.pm - version: '0.65' + version: '0.66' requires: Future: '0.50' XS::Parse::Keyword: '0.13' @@ -38,5 +38,5 @@ requires: resources: IRC: irc://irc.perl.org/#io-async license: http://dev.perl.org/licenses/ -version: '0.65' +version: '0.66' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' diff --git a/hax/perl-additions.c.inc b/hax/perl-additions.c.inc index 939b64b..82cc0f2 100644 --- a/hax/perl-additions.c.inc +++ b/hax/perl-additions.c.inc @@ -173,12 +173,13 @@ static void S_ensure_module_version(pTHX_ SV *module, SV *version) } #if HAVE_PERL_VERSION(5, 16, 0) + /* TODO: perl 5.14 lacks HvNAMEUTF8, gv_fetchmeth_pvn() */ # define fetch_superclass_method_pv(stash, pv, len, level) S_fetch_superclass_method_pv(aTHX_ stash, pv, len, level) static CV *S_fetch_superclass_method_pv(pTHX_ HV *stash, const char *pv, STRLEN len, U32 level) { -#if HAVE_PERL_VERSION(5, 18, 0) +# if HAVE_PERL_VERSION(5, 18, 0) GV *gv = gv_fetchmeth_pvn(stash, pv, len, level, GV_SUPER); -#else +# else SV *superclassname = newSVpvf("%*s::SUPER", HvNAMELEN_get(stash), HvNAME_get(stash)); if(HvNAMEUTF8(stash)) SvUTF8_on(superclassname); @@ -186,13 +187,13 @@ static CV *S_fetch_superclass_method_pv(pTHX_ HV *stash, const char *pv, STRLEN HV *superstash = gv_stashsv(superclassname, GV_ADD); GV *gv = gv_fetchmeth_pvn(superstash, pv, len, level, 0); -#endif +# endif if(!gv) return NULL; return GvCV(gv); } -#endif +#endif /* HAVE_PERL_VERSION(5, 16, 0) */ #define get_class_isa(stash) S_get_class_isa(aTHX_ stash) static AV *S_get_class_isa(pTHX_ HV *stash) diff --git a/hax/perl-backcompat.c.inc b/hax/perl-backcompat.c.inc index 09e521b..5380102 100644 --- a/hax/perl-backcompat.c.inc +++ b/hax/perl-backcompat.c.inc @@ -34,6 +34,16 @@ typedef SV PADNAME; #if !HAVE_PERL_VERSION(5, 22, 0) # define CvPADLIST_set(cv, padlist) (CvPADLIST(cv) = padlist) +# define newPADNAMEpvn(p,n) S_newPADNAMEpvn(aTHX_ p,n) +static PADNAME *S_newPADNAMEpvn(pTHX_ const char *pv, STRLEN n) +{ + PADNAME *pn = newSVpvn(pv, n); + /* PADNAMEs need to be at least SVt_PVNV in order to store the COP_SEQ_* + * fields */ + sv_upgrade(pn, SVt_PVNV); + return pn; +} +# define PadnameREFCNT_dec(pn) SvREFCNT_dec(pn) #endif #ifndef av_count @@ -52,6 +62,10 @@ typedef SV PADNAME; # define block_start(a) Perl_block_start(aTHX_ a) #endif +#ifndef cophh_exists_pvs +# define cophh_exists_pvs(a,b,c) cBOOL(cophh_fetch_pvs(a,b,c)) +#endif + #ifndef cv_clone # define cv_clone(a) Perl_cv_clone(aTHX_ a) #endif @@ -78,6 +92,10 @@ typedef SV PADNAME; # define OpSIBLING(op) ((op)->op_sibling) #endif +#ifndef OpHAS_SIBLING +# define OpHAS_SIBLING(op) (cBOOL(OpSIBLING(op))) +#endif + #ifndef OpMORESIB_set # define OpMORESIB_set(op,sib) ((op)->op_sibling = (sib)) #endif @@ -180,16 +198,18 @@ static bool MY_sv_derived_from_hv(pTHX_ SV *sv, HV *hv) } #endif -#ifdef PERL_USE_GCC_BRACE_GROUPS -# define xV_FROM_REF(XV, ref) \ +#ifndef xV_FROM_REF +# ifdef PERL_USE_GCC_BRACE_GROUPS +# define xV_FROM_REF(XV, ref) \ ({ SV *_ref = ref; assert(SvROK(_ref)); assert(SvTYPE(SvRV(_ref)) == SVt_PV ## XV); (XV *)(SvRV(_ref)); }) -#else -# define xV_FROM_REF(XV, ref) ((XV *)SvRV(ref)) -#endif +# else +# define xV_FROM_REF(XV, ref) ((XV *)SvRV(ref)) +# endif -#define AV_FROM_REF(ref) xV_FROM_REF(AV, ref) -#define CV_FROM_REF(ref) xV_FROM_REF(CV, ref) -#define HV_FROM_REF(ref) xV_FROM_REF(HV, ref) +# define AV_FROM_REF(ref) xV_FROM_REF(AV, ref) +# define CV_FROM_REF(ref) xV_FROM_REF(CV, ref) +# define HV_FROM_REF(ref) xV_FROM_REF(HV, ref) +#endif #ifndef newPADxVOP # define newPADxVOP(type, flags, padix) S_newPADxVOP(aTHX_ type, flags, padix) diff --git a/lib/Future/AsyncAwait.pm b/lib/Future/AsyncAwait.pm index 0d9fe9c..2cc5a7b 100644 --- a/lib/Future/AsyncAwait.pm +++ b/lib/Future/AsyncAwait.pm @@ -3,7 +3,7 @@ # # (C) Paul Evans, 2016-2021 -- leonerd@leonerd.org.uk -package Future::AsyncAwait 0.65; +package Future::AsyncAwait 0.66; use v5.14; use warnings; @@ -495,31 +495,42 @@ modifier can be applied to C. sub import { - my $class = shift; + my $pkg = shift; my $caller = caller; - $class->import_into( $caller, @_ ); + $pkg->import_into( $caller, @_ ); } +sub unimport +{ + my $pkg = shift; + my $caller = caller; + + $pkg->unimport_into( $caller, @_ ); +} + +sub import_into { shift->apply( sub { $^H{ $_[0] }++ }, @_ ) } +sub unimport_into { shift->apply( sub { delete $^H{ $_[0] } }, @_ ) } + my @EXPERIMENTAL = qw( cancel ); -sub import_into +sub apply { - my $class = shift; - my $caller = shift; + my $pkg = shift; + my ( $cb, $caller, @syms ) = @_; - $^H{"Future::AsyncAwait/async"}++; # Just always turn this on + $cb->( "Future::AsyncAwait/async" ); # Just always turn this on - SYM: while( @_ ) { - my $sym = shift; + SYM: while( @syms ) { + my $sym = shift @syms; - $^H{"Future::AsyncAwait/future"} = shift, next if $sym eq "future_class"; + $^H{"Future::AsyncAwait/future"} = shift @syms, next if $sym eq "future_class"; foreach ( @EXPERIMENTAL ) { - $^H{"Future::AsyncAwait/experimental($_)"}++, next SYM if $sym eq ":experimental($_)"; + $cb->( "Future::AsyncAwait/experimental($_)" ), next SYM if $sym eq ":experimental($_)"; } if( $sym eq ":experimental" ) { - $^H{"Future::AsyncAwait/experimental($_)"}++ for @EXPERIMENTAL; + $cb->( "Future::AsyncAwait/experimental($_)" ) for @EXPERIMENTAL; next SYM; } diff --git a/lib/Future/AsyncAwait.xs b/lib/Future/AsyncAwait.xs index 7eb8c7a..80f5b53 100644 --- a/lib/Future/AsyncAwait.xs +++ b/lib/Future/AsyncAwait.xs @@ -2357,6 +2357,7 @@ static void parse_post_newcv(pTHX_ struct XSParseSublikeContext *ctx, void *hook } static struct XSParseSublikeHooks hooks_async = { + .permit_hintkey = "Future::AsyncAwait/async", .flags = XS_PARSE_SUBLIKE_FLAG_PREFIX, .post_blockstart = parse_post_blockstart, diff --git a/lib/Future/AsyncAwait/Awaitable.pm b/lib/Future/AsyncAwait/Awaitable.pm index 89ca9e3..a7ffac2 100644 --- a/lib/Future/AsyncAwait/Awaitable.pm +++ b/lib/Future/AsyncAwait/Awaitable.pm @@ -3,7 +3,7 @@ # # (C) Paul Evans, 2019-2022 -- leonerd@leonerd.org.uk -package Future::AsyncAwait::Awaitable 0.65; +package Future::AsyncAwait::Awaitable 0.66; use v5.14; use warnings; diff --git a/lib/Future/AsyncAwait/ExtensionBuilder.pm b/lib/Future/AsyncAwait/ExtensionBuilder.pm index 389218a..5426c28 100644 --- a/lib/Future/AsyncAwait/ExtensionBuilder.pm +++ b/lib/Future/AsyncAwait/ExtensionBuilder.pm @@ -3,14 +3,14 @@ # # (C) Paul Evans, 2022 -- leonerd@leonerd.org.uk -package Future::AsyncAwait::ExtensionBuilder 0.65; +package Future::AsyncAwait::ExtensionBuilder 0.66; use v5.14; use warnings; =head1 NAME -C - build-time support for extensions to C +C - build-time support for extensions to C =head1 SYNOPSIS diff --git a/lib/Future/AsyncAwait/ExtensionBuilder_data.pm.PL b/lib/Future/AsyncAwait/ExtensionBuilder_data.pm.PL index f2f5df3..752b071 100644 --- a/lib/Future/AsyncAwait/ExtensionBuilder_data.pm.PL +++ b/lib/Future/AsyncAwait/ExtensionBuilder_data.pm.PL @@ -19,7 +19,7 @@ $outh->print( scalar do { <$in_h> } ); __DATA__ -package Future::AsyncAwait::ExtensionBuilder_data 0.65; +package Future::AsyncAwait::ExtensionBuilder_data 0.66; use v5.14; use warnings; diff --git a/lib/Test/Future/AsyncAwait/Awaitable.pm b/lib/Test/Future/AsyncAwait/Awaitable.pm index 8b4d19c..80f3801 100644 --- a/lib/Test/Future/AsyncAwait/Awaitable.pm +++ b/lib/Test/Future/AsyncAwait/Awaitable.pm @@ -3,7 +3,7 @@ # # (C) Paul Evans, 2020-2023 -- leonerd@leonerd.org.uk -package Test::Future::AsyncAwait::Awaitable 0.65; +package Test::Future::AsyncAwait::Awaitable 0.66; use v5.14; use warnings; diff --git a/t/01async-immediate.t b/t/01async-immediate.t index 726cb05..bca958a 100644 --- a/t/01async-immediate.t +++ b/t/01async-immediate.t @@ -81,4 +81,13 @@ use Future::AsyncAwait; isa_ok( shift @ret, [ "Future" ], 'Single result was a Future' ); } +# unimport +{ + no Future::AsyncAwait; + + sub async { return "normal function" } + + is( async, "normal function", 'async() parses as a normal function call' ); +} + done_testing; diff --git a/t/70await+feature-class.t b/t/70await+feature-class.t new file mode 100644 index 0000000..782d886 --- /dev/null +++ b/t/70await+feature-class.t @@ -0,0 +1,70 @@ +#!/usr/bin/perl + +use v5.14; +use warnings; + +use Test2::V0 0.000148; # is_oneref + +BEGIN { + plan skip_all => "Future >= 0.49 is not available" + unless eval { require Future; + Future->VERSION( '0.49' ) }; + plan skip_all => "Future::AsyncAwait >= 0.45 is not available" + unless eval { require Future::AsyncAwait; + Future::AsyncAwait->VERSION( '0.45' ) }; + # version 5.37.10 added the ability to start_subparse() with CVf_IsMETHOD, + # which we need + plan skip_all => "feature 'class' is not available" + unless $^V ge v5.37.10; + plan skip_all => "XS::Parse::Sublike >= 0.17 is not in use" + unless $XS::Parse::Sublike::VERSION >= 0.17; + + # If Future::XS is installed, then check it's at least 0.08; earlier + # versions will crash + if( eval { require Future::XS } ) { + plan skip_all => "Future::XS is installed but it is older than 0.08" + unless eval { Future::AsyncAwait->VERSION( '0.08' ); }; + } + + diag( "Future::AsyncAwait $Future::AsyncAwait::VERSION, " . + "core perl version $^V" ); +} + +use Future::AsyncAwait; + +use feature 'class'; +no warnings 'experimental::class'; + +# async method +{ + class Thunker { + field $_times_thunked = 0; + + method count { $_times_thunked } + + async method thunk { + my ( $f ) = @_; + await $f; + $_times_thunked++; + return "result"; + } + } + + my $thunker = Thunker->new; + is_oneref( $thunker, 'after ->new' ); + + my $f1 = Future->new; + my $fret = $thunker->thunk( $f1 ); + is_refcount( $thunker, 2, 'during async sub' ); + + is( $thunker->count, 0, 'count is 0 before $f1->done' ); + + $f1->done; + + is_oneref( $thunker, 'after ->done' ); + + is( $thunker->count, 1, 'count is 1 after $f1->done' ); + is( $fret->get, "result", '$fret for await in async method' ); +} + +done_testing; diff --git a/t/80async-method.t b/t/80async-method.t index 152fd22..f5b8c5a 100644 --- a/t/80async-method.t +++ b/t/80async-method.t @@ -3,7 +3,7 @@ use v5.14; use warnings; -use Test2::V0 0.000148; # is_oneref +use Test2::V0 0.000148; # is_refcount BEGIN { plan skip_all => "Future >= 0.49 is not available" @@ -12,9 +12,9 @@ BEGIN { plan skip_all => "Future::AsyncAwait >= 0.45 is not available" unless eval { require Future::AsyncAwait; Future::AsyncAwait->VERSION( '0.45' ) }; - plan skip_all => "Object::Pad >= 0.73 is not available" + plan skip_all => "Object::Pad >= 0.800 is not available" unless eval { require Object::Pad; - Object::Pad->VERSION( '0.73' ) }; + Object::Pad->VERSION( '0.800' ) }; # If Future::XS is installed, then check it's at least 0.08; earlier # versions will crash @@ -24,7 +24,7 @@ BEGIN { } Future::AsyncAwait->import; - Object::Pad->import( ':experimental(init_expr)' ); + Object::Pad->import; diag( "Future::AsyncAwait $Future::AsyncAwait::VERSION, " . "Object::Pad $Object::Pad::VERSION" ); diff --git a/t/81async-method+dynamically.t b/t/81async-method+dynamically.t index 9ac3a59..2279176 100644 --- a/t/81async-method+dynamically.t +++ b/t/81async-method+dynamically.t @@ -11,15 +11,15 @@ BEGIN { plan skip_all => "Future::AsyncAwait >= 0.40 is not available" unless eval { require Future::AsyncAwait; Future::AsyncAwait->VERSION( '0.40' ) }; - plan skip_all => "Object::Pad >= 0.73 is not available" + plan skip_all => "Object::Pad >= 0.800 is not available" unless eval { require Object::Pad; - Object::Pad->VERSION( '0.73' ) }; + Object::Pad->VERSION( '0.800' ) }; plan skip_all => "Syntax::Keyword::Dynamically >= 0.04 is not available" unless eval { require Syntax::Keyword::Dynamically; Syntax::Keyword::Dynamically->VERSION( '0.04' ) }; Future::AsyncAwait->import; - Object::Pad->import( ':experimental(init_expr)' ); + Object::Pad->import; Syntax::Keyword::Dynamically->import; diag( "Future::AsyncAwait $Future::AsyncAwait::VERSION, " . -- cgit v1.2.3