headzoo / surf

Stateful programmatic web browsing in Go.
MIT License
1.49k stars 160 forks source link

forms not found #123

Open swizzley opened 4 years ago

swizzley commented 4 years ago

I've tried selecting this form 9 ways from sunday, and finally tried bow.Forms() only to find the array is empty. Am I on a bad branch or something?

commit a4a8c16c01dc47ef3a25326d21745806f3e6797a (HEAD -> master, origin/master, origin/HEAD)
Merge: 5d4e44e 2f714b5
Author: Sean Hickey <sean@headzoo.io>
Date:   Sun Sep 9 09:48:44 2018 -0400

    Merge pull request #108 from mattn/selected

    [FIX] Handle selected options
<form name="f1" id="i0281" novalidate="novalidate" spellcheck="false" method="post" target="_top" autocomplete="off" data-bind="autoSubmit: forceSubmit, attr: { action: postUrl }, ariaHidden: activeDialog" action="https://login.microsoftonline.com/906aefe9-76a7-4f65-b82d-5ec20775d5aa/login"> <!-- ko if: svr.iBannerEnvironment --><!-- /ko --> <!-- ko withProperties: { '$loginPage': $data } --> <div class="outer" data-bind="component: { name: 'master-page',
        params: {
            serverData: svr,
            showButtons: svr.fShowButtons,
            showFooterLinks: true,
            useWizardBehavior: svr.fUseWizardBehavior,
            handleWizardButtons: false,
            password: password,
            hideFromAria: ariaHidden },
        event: {
            footerAgreementClick: footer_agreementClick } }"><!-- ko template: { nodes: $componentTemplateNodes, data: $parent } --> <!-- ko if: svr.fShowCookieBanner --><!-- /ko --> <div class="middle" data-bind="css: { 'app': backgroundLogoUrl }"> <!-- ko if: backgroundLogoUrl() && !(paginationControlMethods() && paginationControlMethods().currentViewHasMetadata('hideLogo')) --><!-- /ko --> <!-- ko if: svr.fShowPageLevelTitleAndDesc && !(paginationControlMethods() && paginationControlMethods().currentViewHasMetadata('hidePageLevelTitleAndDesc')) --><!-- /ko --> <div data-bind="
                animationEnd: paginationControlMethods() &amp;&amp; paginationControlMethods().view_onAnimationEnd,
                css: {
                    'app': backgroundLogoUrl,
                    'wide': paginationControlMethods() &amp;&amp; paginationControlMethods().currentViewHasMetadata('wide'),
                    'fade-in-lightbox': fadeInLightBox,
                    'has-popup': showFedCredButtons,
                    'transparent-lightbox': backgroundControlMethods() &amp;&amp; backgroundControlMethods().useTransparentLightBox },
                externalCss: { 'sign-in-box': true }" class="sign-in-box ext-sign-in-box fade-in-lightbox"> <div class="lightbox-cover" data-bind="css: { 'disable-lightbox': svr.fAllowGrayOutLightBox &amp;&amp; showLightboxProgress() }"></div> <!-- ko if: showLightboxProgress --><!-- /ko --> <div class="win-scroll"> <!-- ko ifnot: paginationControlMethods() && (paginationControlMethods().currentViewHasMetadata('hideLogo')) --> <div data-bind="component: { name: 'logo-control',
                        params: {
                            isChinaDc: svr.fIsChinaDc,
                            bannerLogoUrl: bannerLogoUrl() } }"><!--  --> <!-- ko if: bannerLogoUrl --> <img class="banner-logo" role="presentation" data-bind="attr: { src: bannerLogoUrl }" src="https://aadcdn.msauthimages.net/dbd5a2dd-kc1bfaqym8t7tiikhd0ciypq-fv2o-vdk53zxlj8asi/logintenantbranding/0/bannerlogo?ts=636107720378996794"> <!-- /ko --> <!-- ko if: !bannerLogoUrl && !isChinaDc --><!-- /ko --></div> <!-- /ko --> <!-- ko if: svr.strLWADisclaimerMsg && (paginationControlMethods() && !paginationControlMethods().currentViewHasMetadata('hideLwaDisclaimer')) --><!-- /ko --> <!-- ko if: asyncInitReady --> <div role="main" data-bind="component: { name: 'pagination-control',
                            publicMethods: paginationControlMethods,
                            params: {
                                enableCssAnimation: svr.fEnableCssAnimation,
                                disableAnimationIfAnimationEndUnsupported: svr.fDisableAnimationIfAnimationEndUnsupported,
                                initialViewId: initialViewId,
                                currentViewId: currentViewId,
                                initialSharedData: initialSharedData,
                                initialError: $loginPage.getServerError() },
                            event: {
                                cancel: paginationControl_onCancel,
                            loadView: view_onLoadView,
                            showView: view_onShow,
                                setLightBoxFadeIn: view_onSetLightBoxFadeIn,
                                animationStateChange: paginationControl_onAnimationStateChange } }"><!--  --> <div data-bind="css: { 'zero-opacity': hidePaginatedView() }" class=""> <!-- ko if: showIdentityBanner() && (sharedData.displayName || svr.sPOST_Username) --><!-- /ko --> <div class="pagination-view animate slide-in-next" data-bind="css: {
        'has-identity-banner': showIdentityBanner() &amp;&amp; (sharedData.displayName || svr.sPOST_Username),
        'zero-opacity': hidePaginatedView.hideSubView(),
        'animate': animate(),
        'slide-out-next': animate.isSlideOutNext(),
        'slide-in-next': animate.isSlideInNext(),
        'slide-out-back': animate.isSlideOutBack(),
        'slide-in-back': animate.isSlideInBack() }"> <!-- ko foreach: views --> <!-- ko if: $parent.currentViewIndex() === $index() --> <!-- ko template: { nodes: [$data], data: $parent } --><div data-viewid="1" data-showfedcredbutton="true" data-bind="pageViewComponent: { name: 'login-paginated-username-view',
                            params: {
                                serverData: svr,
                                serverError: initialError,
                                isInitialView: isInitialState,
                                displayName: sharedData.displayName,
                                otherIdpRedirectUrl: sharedData.otherIdpRedirectUrl,
                                prefillNames: $loginPage.prefillNames,
                                flowToken: sharedData.flowToken },
                            event: {
                                redirect: $loginPage.view_onRedirect,
                                setPendingRequest: $loginPage.view_onSetPendingRequest,
                                registerDialog: $loginPage.view_onRegisterDialog,
                                unregisterDialog: $loginPage.view_onUnregisterDialog,
                                showDialog: $loginPage.view_onShowDialog,
                                agreementClick: $loginPage.footer_agreementClick } }"><!--  --> <div data-bind="component: { name: 'header-control',
    params: {
        serverData: svr,
        title: str['WF_STR_HeaderDefault_Title'] } }"><div class="row title ext-title" id="loginHeader" data-bind="externalCss: { 'title': true }"> <div role="heading" aria-level="1" data-bind="text: title">Sign in</div> <!-- ko if: isSubtitleVisible --><!-- /ko --> </div></div> <!-- ko if: pageDescription && !svr.fHideLoginDesc --><!-- /ko --> <div class="row"> <div role="alert" aria-live="assertive"> <!-- ko if: usernameTextbox.error --><!-- /ko --> </div> <div class="form-group col-md-24"> <!-- ko if: prefillNames().length > 1 --><!-- /ko --> <!-- ko ifnot: prefillNames().length > 1 --> <div class="placeholderContainer" data-bind="component: { name: 'placeholder-textbox-field',
            publicMethods: usernameTextbox.placeholderTextboxMethods,
            params: {
                serverData: svr,
                hintText: tenantBranding.UserIdLabel || str['CT_PWD_STR_Email_Example'],
                hintCss: 'placeholder' + (!svr.fAllowPhoneSignIn ? ' ltr_override' : '') },
            event: {
                updateFocus: usernameTextbox.textbox_onUpdateFocus } }"><!-- ko withProperties: { '$placeholderText': placeholderText } --> <!-- ko template: { nodes: $componentTemplateNodes, data: $parent } --> <input type="email" name="loginfmt" id="i0116" maxlength="113" lang="en" class="form-control ltr_override input ext-input text-box ext-text-box" aria-required="true" data-bind="
                    externalCss: {
                        'input': true,
                        'text-box': true,
                        'has-error': usernameTextbox.error },
                    ariaLabel: tenantBranding.UserIdLabel || str['CT_PWD_STR_Username_AriaLabel'],
                    ariaDescribedBy: 'loginHeader' + (pageDescription &amp;&amp; !svr.fHideLoginDesc ? ' loginDescription' : ''),
                    textInput: usernameTextbox.value,
                    hasFocusEx: usernameTextbox.focused,
                    placeholder: $placeholderText" aria-label="Enter your email, phone, or Skype." aria-describedby="loginHeader" placeholder="Email, phone, or Skype"> <input name="passwd" type="password" id="i0118" autocomplete="off" data-bind="moveOffScreen, textInput: passwordBrowserPrefill" class="moveOffScreen" tabindex="-1" aria-hidden="true"> <!-- /ko --> <!-- /ko --> <!-- ko ifnot: usePlaceholderAttribute --><!-- /ko --></div> <!-- /ko --> </div> </div> <div data-bind="css: { 'position-buttons': !tenantBranding.BoilerPlateText }" class="position-buttons"> <div class="row"> <div class="col-md-24"> <div class="text-13"> <!-- ko if: svr.fCBShowSignUp && !svr.fDoIfExists && !svr.fCheckProofForAliases --><!-- /ko --> <!-- ko if: svr.showCantAccessAccountLink --> <div class="form-group"> <a id="cantAccessAccount" name="cannotAccessAccount" data-bind="
                        text: str['WF_STR_CantAccessAccount_Text'],
                        click: cantAccessAccount_onClick,
                        href: accessRecoveryLink || '#'" href="#">Can’t access your account?</a> </div> <!-- /ko --> <!-- ko if: showFidoLinkInline && hasFido() && (availableCredsWithoutUsername().length >= 2 || svr.fShowForgotUsernameLink) --><!-- /ko --> <!-- ko if: (availableCredsWithoutUsername().length > 0 || svr.fShowForgotUsernameLink) && !hideSignInOptions --> <div class="form-group" data-bind="
                    component: { name: 'cred-switch-link-control',
                        params: {
                            serverData: svr,
                            availableCreds: availableCredsWithoutUsername(),
                            showForgotUsername: svr.fShowForgotUsernameLink },
                        event: {
                            switchView: noUsernameCredSwitchLink_onSwitchView,
                            redirect: onRedirect,
                            registerDialog: onRegisterDialog,
                            unregisterDialog: onUnregisterDialog,
                            showDialog: onShowDialog } }"><!--  --> <div class="form-group"> <!-- ko if: credentialCount > 1 || (credentialCount === 1 && (showForgotUsername || selectedCredShownOnlyOnPicker)) --> <a id="idA_PWD_SwitchToCredPicker" href="#" data-bind="
        text: isUserKnown ? str['CT_PWD_STR_SwitchToCredPicker_Link'] : str['CT_PWD_STR_SwitchToCredPicker_Link_NoUser'],
        click: switchToCredPicker_onClick">Sign-in options</a> <!-- /ko --> <!-- ko if: credentialCount === 1 && !(showForgotUsername || selectedCredShownOnlyOnPicker) --><!-- /ko --> <!-- ko if: credentialCount === 0 && showForgotUsername --><!-- /ko --> </div> <!-- ko if: credLinkError --><!-- /ko --></div> <!-- /ko --> </div> </div> </div> </div> <!-- ko if: svr.fShowLegalMessagingInline --><!-- /ko --> <div class="win-button-pin-bottom"> <div class="row" data-bind="css: { 'move-buttons': tenantBranding.BoilerPlateText }"> <div data-bind="component: { name: 'footer-buttons-field',
            params: {
                serverData: svr,
                isPrimaryButtonEnabled: !isRequestPending(),
                isPrimaryButtonVisible: svr.fShowButtons,
                isSecondaryButtonEnabled: true,
                isSecondaryButtonVisible: svr.fShowButtons &amp;&amp; isBackButtonVisible() },
            event: {
                primaryButtonClick: primaryButton_onClick,
                secondaryButtonClick: secondaryButton_onClick } }"><div class="col-xs-24 no-padding-left-right button-container" data-bind="
    visible: isPrimaryButtonVisible() || isSecondaryButtonVisible(),
    css: { 'no-margin-bottom': removeBottomMargin }"> <!-- ko if: isSecondaryButtonVisible --><!-- /ko --> <div data-bind="css: { 'inline-block': isPrimaryButtonVisible }" class="inline-block"> <!-- type="submit" is needed in-addition to 'type' in primaryButtonAttributes observable to support IE8 --> <input type="submit" id="idSIButton9" data-bind="
            attr: primaryButtonAttributes,
            externalCss: {
                'button': true,
                'primary': true },
            value: primaryButtonText() || str['CT_PWD_STR_SignIn_Button_Next'],
            hasFocus: focusOnPrimaryButton,
            click: primaryButton_onClick,
            enable: isPrimaryButtonEnabled,
            visible: isPrimaryButtonVisible,
            preventTabbing: primaryButtonPreventTabbing" class="button ext-button primary ext-primary" value="Next"> </div> </div></div> </div> </div> <!-- ko if: tenantBranding.BoilerPlateText --><!-- /ko --></div><!-- /ko --> <!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko -->  <!-- ko if: $parent.currentViewIndex() === $index() --><!-- /ko --> <!-- /ko --> </div> </div></div> <!-- /ko --> </div> </div> <!-- ko if: showDebugDetails --><!-- /ko --> <!-- ko if: showFedCredButtons --><!-- /ko --> <!-- ko if: newSession --><!-- /ko --> <input type="hidden" name="ps" data-bind="value: postedLoginStateViewId" value=""> <input type="hidden" name="psRNGCDefaultType" data-bind="value: postedLoginStateViewRNGCDefaultType" value=""> <input type="hidden" name="psRNGCEntropy" data-bind="value: postedLoginStateViewRNGCEntropy" value=""> <input type="hidden" name="psRNGCSLK" data-bind="value: postedLoginStateViewRNGCSLK" value=""> <input type="hidden" name="canary" data-bind="value: svr.canary" value="srYCHDH7BKi8OO9/Sceab7O0twu039GIc7Ig/T6qU14=1:1"> <input type="hidden" name="ctx" data-bind="value: ctx" value="rQIIAdNiNtIzsFIxSDQ2M0g2NtRNMzAy1DWxsDDQTTJNNNc1MDFNNjBONTVNs7AoEuISYJoazbvp-ln3PUbhsgYrRc-tYlTNKCkpKLbS109JLM7IS0zJ10vOz01OLC7Ry0st0U9OzMlJSkzO3sHIeIGR8QUj4y0mfn_H0pIMIxCRX5RZlTqLmQ1Ip2fmrWJWMYAAY10QCSGSYSwY2MSsYmlglpialmqpa24GdKNJmpmpbpKFUYquaWqykYG5uWmKaWLiKWb1_ILUvMwUhYKi_LTMnFSF1NzEzByFlMyi1OSS_KJKvaLUxBQ9oPtuMDNeYGF8xcJjwGrFwcElwCfBpsDwg4VxESvQwzOSuMNuGIk59xUIBu5ocmM4xapfXBTp7OHiYe7knWnh72-pH5ycmphk7m9QUl5qYGzp7pls7pmuH2JWGGpoYmtoZTiBjfEDG2MHO8MuTuLC6gAvAwA1"> <input type="hidden" name="hpgrequestid" data-bind="value: svr.sessionId" value="560b6298-32d8-4316-8e70-1151b8824600"> <input type="hidden" id="i0327" data-bind="attr: { name: svr.sFTName }, value: flowToken" name="flowToken" value="AQABAAEAAAB2UyzwtQEKR7-rWbgdcBZI_yIibNPzgD-FFYTzQ4qDVkx0InTr1zlu69scnRzNmqu4pFIbtBR6GhPDsk99mfLHO4OCJmQPIW32QvXuBFitDH8KcQ_MPx0qFXW_r3kSD98oV3TjTU37fhk6JPLM0p69syHtRwHfkzhdJRXAhLxtbURL8Egee0U-r-Tu-O1smgawoW75mWktg8gmZWeb9Nl5MPUwNajCece0FpVVL2KTVDRWnYXgrSOy_h_TnNVaGa_SMssAeVpc_3kRTcvLQNMI4TYcy5P2N5ZB4o8fobplpLLbtzymMHAOI-c4ZBImlfub1H9dgRVfoftokWC_Hw6PlbipfGml77ETudkQXA394z1AxRqEqD2Ymc0OtuCJg4bHOxaLcx3vsO5g5K_BYMSMjM202dgrKZIP4sjErtOYohabLLMQinB9Vc5jo9CAz9ykz8k_eh66zdcN294sogiyNvQLlXOQjrqYQa8GibdN6SAA"> <input type="hidden" name="PPSX" data-bind="value: svr.sRandomBlob" value=""> <input type="hidden" name="NewUser" value="1"> <input type="hidden" name="FoundMSAs" data-bind="value: svr.sFoundMSAs" value=""> <input type="hidden" name="fspost" data-bind="value: svr.fPOST_ForceSignin ? 1 : 0" value="0"> <input type="hidden" name="i21" data-bind="value: wasLearnMoreShown() ? 1 : 0" value="0"> <input type="hidden" name="CookieDisclosure" data-bind="value: svr.fShowCookieBanner ? 1 : 0" value="0"> <input type="hidden" name="IsFidoSupported" data-bind="value: isFidoSupported() ? 1 : 0" value="1"> <input type="hidden" name="isSignupPost" data-bind="value: isSignupPost() ? 1 : 0" value="0"> <div data-bind="component: { name: 'instrumentation-control',
                publicMethods: instrumentationMethods,
                params: { serverData: svr } }"><input type="hidden" name="i2" data-bind="value: clientMode" value="1"> <input type="hidden" name="i17" data-bind="value: srsFailed" value=""> <input type="hidden" name="i18" data-bind="value: srsSuccess" value=""> <input type="hidden" name="i19" data-bind="value: timeOnPage" value=""></div> <!-- ko ifnot: svr.fHideFooter --> <div id="footer" role="contentinfo" data-bind="
                css: {
                    'default': !backgroundLogoUrl(),
                    'new-background-image': useNewDefaultBackground },
                externalCss: { 'footer': true }" class="default footer ext-footer"> <div data-bind="component: { name: 'footer-control',
                    publicMethods: footerMethods,
                    params: {
                        serverData: svr,
                        useNewDefaultBackground: useNewDefaultBackground(),
                        hasDarkBackground: backgroundLogoUrl(),
                        showLinks: true },
                    event: {
                        agreementClick: footer_agreementClick,
                        showDebugDetails: toggleDebugDetails_onClick } }"><!--  --> <!-- ko if: !hideFooter && (showLinks || impressumLink || showIcpLicense) --> <div id="footerLinks" class="footerNode text-secondary"> <!-- ko if: !hideTOU --> <a id="ftrTerms" data-bind="text: termsText, href: termsLink, click: termsLink_onClick" href="https://www.microsoft.com/en-US/servicesagreement/">Terms of use</a> <!-- /ko --> <!-- ko if: !hidePrivacy --> <a id="ftrPrivacy" data-bind="text: privacyText, href: privacyLink, click: privacyLink_onClick" href="https://privacy.microsoft.com/en-US/privacystatement">Privacy &amp; cookies</a> <!-- /ko --> <!-- ko if: impressumLink --><!-- /ko --> <!-- ko if: showIcpLicense --><!-- /ko --> <!-- Set attr binding before hasFocusEx to prevent Narrator from losing focus --> <a id="moreOptions" href="#" role="button" class="moreOptions" data-bind="
        click: moreInfo_onClick,
        ariaLabel: str['CT_STR_More_Options_Ellipsis_AriaLabel'],
        attr: { 'aria-expanded': showDebugDetails().toString() },
        hasFocusEx: focusMoreInfo()" aria-label="Click here for troubleshooting information" aria-expanded="false"> <!-- ko component: { name: 'accessible-image-control', params: { hasDarkBackground: !useNewDefaultBackground } } --><!-- ko if: (isHighContrastBlackTheme || hasDarkBackground || svr.fHasBackgroundColor) && !isHighContrastWhiteTheme --> <!-- ko template: { nodes: [lightImageNode], data: $parent } --><img class="desktopMode" role="presentation" pngsrc="https://aadcdn.msftauth.net/shared/1.0/content/images/ellipsis_white_0ad43084800fd8b50a2576b5173746fe.png" svgsrc="https://aadcdn.msftauth.net/shared/1.0/content/images/ellipsis_white_5ac590ee72bfe06a7cecfd75b588ad73.svg" data-bind="imgSrc" src="https://aadcdn.msftauth.net/shared/1.0/content/images/ellipsis_white_5ac590ee72bfe06a7cecfd75b588ad73.svg"><!-- /ko --> <!-- /ko --> <!-- ko if: (isHighContrastWhiteTheme || (!hasDarkBackground && !svr.fHasBackgroundColor)) && !isHighContrastBlackTheme --><!-- /ko --><!-- /ko --> <!-- ko component: { name: 'accessible-image-control', params: { hasDarkBackground: hasDarkBackground } } --><!-- ko if: (isHighContrastBlackTheme || hasDarkBackground || svr.fHasBackgroundColor) && !isHighContrastWhiteTheme --><!-- /ko --> <!-- ko if: (isHighContrastWhiteTheme || (!hasDarkBackground && !svr.fHasBackgroundColor)) && !isHighContrastBlackTheme --> <!-- ko template: { nodes: [darkImageNode], data: $parent } --><img class="mobileMode" role="presentation" pngsrc="https://aadcdn.msftauth.net/shared/1.0/content/images/ellipsis_grey_5bc252567ef56db648207d9c36a9d004.png" svgsrc="https://aadcdn.msftauth.net/shared/1.0/content/images/ellipsis_grey_2b5d393db04a5e6e1f739cb266e65b4c.svg" data-bind="imgSrc" src="https://aadcdn.msftauth.net/shared/1.0/content/images/ellipsis_grey_2b5d393db04a5e6e1f739cb266e65b4c.svg"><!-- /ko --> <!-- /ko --><!-- /ko --> </a> </div> <!-- /ko --> <!-- ko if: svr.fShowLegalMessagingInline && showLinks --><!-- /ko --></div> </div> <!-- /ko --> </div> <!-- /ko --></div> <!-- /ko --> </form>
chnrxn commented 3 years ago

This code might have something to do with what you are seeing (but I notice you did not post any logs/output) https://github.com/headzoo/surf/blob/master/browser/browser.go#L381:L384

Appending to an allocated slice actually starts appending from the end of the slice, meaning the first few items would be nil.

https://play.golang.org/p/xcoVT0Rpqk2 has some demo code that shows this.

chnrxn commented 3 years ago

I have submitted this PR https://github.com/headzoo/surf/pull/125 to fix the issue.