Fixes https://github.com/aspnet/AspNetCore/issues/9901
This commit is contained in:
parent
58554c094f
commit
d935ea2d25
|
|
@ -124,7 +124,6 @@
|
|||
<NodeJsProjects Include="
|
||||
$(RepoRoot)src\SignalR\**\*.npmproj;
|
||||
$(RepoRoot)src\Middleware\**\*.npmproj;
|
||||
$(RepoRoot)src\Components\Browser.JS\**\*.npmproj;
|
||||
"
|
||||
RestoreInParallel="false"
|
||||
Exclude="@(ProjectToExclude)" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
const packageJson = args[0];
|
||||
const packageVersion = args[1];
|
||||
|
||||
const fileContent = fs.readFileSync(packageJson);
|
||||
const updatedContent = fileContent.toString().replace(/\"link:.*\"/g, `">=${packageVersion}"`);
|
||||
if (fileContent != updatedContent) {
|
||||
fs.writeFileSync(packageJson, updatedContent);
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)' == ''">$(MSBuildProjectDirectory)\obj\</BaseIntermediateOutputPath>
|
||||
<IntermediateOutputPath>$([MSBuild]::NormalizeDirectory('$(BaseIntermediateOutputPath)'))$(Configuration)\</IntermediateOutputPath>
|
||||
<InstallArgs Condition="'$(RestoreLockedMode)' == 'true'">--frozen-lockfile</InstallArgs>
|
||||
<_BackupPackageJson>$(IntermediateOutputPath)$(MSBuildProjectName).package.json.bak</_BackupPackageJson>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="_CheckForInvalidConfiguration">
|
||||
|
|
@ -47,13 +48,13 @@
|
|||
|
||||
<Target Name="Pack" Condition="'$(IsPackable)' == 'true'" DependsOnTargets="$(PackDependsOn)">
|
||||
<PropertyGroup>
|
||||
<_BackupPackageJson>$(IntermediateOutputPath)$(MSBuildProjectName).package.json.bak</_BackupPackageJson>
|
||||
<_PackageTargetPath>$(MSBuildProjectDirectory)\$(PackageFileName)</_PackageTargetPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<Copy SourceFiles="$(PackageJson)" DestinationFiles="$(_BackupPackageJson)" />
|
||||
|
||||
<Yarn Command="version --no-git-tag-version --new-version $(PackageVersion)" />
|
||||
<Exec Command="node $(MSBuildThisFileDirectory)..\scripts\update-packagejson-links.js $(PackageJson) $(PackageVersion)" />
|
||||
<Yarn Command="pack --filename $(PackageFileName)" />
|
||||
|
||||
<Move SourceFiles="$(_PackageTargetPath)" DestinationFolder="$(PackageOutputPath)" />
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
node_modules/
|
||||
*.js.map
|
||||
dist/Debug/
|
||||
|
|
|
|||
|
|
@ -7,23 +7,10 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<WebpackInputs Include="src\**\*.ts" />
|
||||
<WebPackOutputs Include="dist\Debug\blazor.webassembly.js" />
|
||||
<WebPackOutputs Include="dist\Release\blazor.webassembly.js" />
|
||||
<WebPackOutputs Include="dist\Debug\blazor.server.js" />
|
||||
<WebPackOutputs Include="dist\Release\blazor.server.js" />
|
||||
<ProjectReference Include="..\..\SignalR\clients\ts\signalr\signalr.npmproj" />
|
||||
<ProjectReference Include="..\..\SignalR\clients\ts\signalr-protocol-msgpack\signalr-protocol-msgpack.npmproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Directory.Build.targets))\Directory.Build.targets" />
|
||||
|
||||
<!-- Override the default 'Build' target from eng/targets/Npm.Common.targets. -->
|
||||
<Target Name="Build"
|
||||
Inputs="@(WebpackInputs)"
|
||||
Outputs="@(WebPackOutputs)">
|
||||
<RemoveDir Directories="dist" />
|
||||
|
||||
<Yarn Command="run build:debug" />
|
||||
<Yarn Command="run build:production" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
# Prevent generated files from showing up in git and GitHub diffs. See https://www.git-scm.com/docs/gitattributes#_defining_macro_attributes, https://github.com/github/linguist#generated-code
|
||||
*.js -diff -merge
|
||||
*.js linguist-generated=true
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -11,8 +11,8 @@
|
|||
"test": "jest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aspnet/signalr": "^1.0.0",
|
||||
"@aspnet/signalr-protocol-msgpack": "^1.0.0",
|
||||
"@aspnet/signalr": "link:../../SignalR/clients/ts/signalr",
|
||||
"@aspnet/signalr-protocol-msgpack": "link:../../SignalR/clients/ts/signalr-protocol-msgpack",
|
||||
"@dotnet/jsinterop": "3.0.0-preview6.19280.1",
|
||||
"@types/emscripten": "0.0.31",
|
||||
"@types/jest": "^24.0.6",
|
||||
|
|
|
|||
|
|
@ -2,21 +2,13 @@
|
|||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@aspnet/signalr-protocol-msgpack@^1.0.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@aspnet/signalr-protocol-msgpack/-/signalr-protocol-msgpack-1.1.0.tgz#155038149e8e0eee1f97f4d1319f9f3271ff06fb"
|
||||
integrity sha512-AQv5AavWvoFz2iLSIDK1DAIXMNhQ1Jt1qRDouXxLKAKP13u8iFq7i3/MwJ30ShOBGBoL5/zn6pBlNjAzTmAsMA==
|
||||
dependencies:
|
||||
msgpack5 "^4.0.2"
|
||||
"@aspnet/signalr-protocol-msgpack@link:../../SignalR/clients/ts/signalr-protocol-msgpack":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
"@aspnet/signalr@^1.0.0":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@aspnet/signalr/-/signalr-1.1.2.tgz#eb9cbc758ff5bfe9a2aba6669e05dfc25a6d783d"
|
||||
integrity sha512-Xu2ndFTWYhyE+TOCK3LkPWGmc5xGLezBKgGEchyOA++alJ6fdWJ8P/Wsb4Mmd1buzcxGLlIyjpLfUP20rrCHIg==
|
||||
dependencies:
|
||||
eventsource "^1.0.7"
|
||||
request "^2.88.0"
|
||||
ws "^6.0.0"
|
||||
"@aspnet/signalr@link:../../SignalR/clients/ts/signalr":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
"@babel/code-frame@^7.0.0":
|
||||
version "7.0.0"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
|
|
@ -50,10 +50,18 @@
|
|||
<Compile Include="$(MessagePackRoot)SequenceReaderExtensions.cs" LinkBase="BlazorPack\MessagePack" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="..\..\Browser.JS\dist\$(Configuration)\blazor.server.js" LogicalName="_framework/%(Filename)%(Extension)" />
|
||||
<PropertyGroup>
|
||||
<!--
|
||||
We check in the Release / Production build of blazor.*.js, but not the Debug builds. Consequently the former is always available to embed, the latter is only available
|
||||
if Browser.JS was built locally. Use the Debug build when available and building in Debug configuration.
|
||||
-->
|
||||
<BlazorServerJSFile>..\..\Browser.JS\dist\Release\blazor.server.js</BlazorServerJSFile>
|
||||
<BlazorServerJSFile Condition="'$(Configuration)' == 'Debug' AND Exists('..\..\Browser.JS\dist\Debug\blazor.server.js')">..\..\Browser.JS\dist\Debug\blazor.server.js</BlazorServerJSFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<EmbeddedResource Include="..\..\Browser.JS\dist\$(Configuration)\blazor.server.js.map" LogicalName="_framework/%(Filename)%(Extension)" Condition="Exists('..\..\Browser.JS\dist\$(Configuration)\blazor.server.js.map')" />
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="$(BlazorServerJSFile)" LogicalName="_framework/%(Filename)%(Extension)" />
|
||||
<EmbeddedResource Include="$(BlazorServerJSFile).map" LogicalName="_framework/%(Filename)%(Extension)" Condition="Exists('$(BlazorServerJSFile).map')" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -37,11 +37,6 @@
|
|||
<span class="oi oi-list-rich" aria-hidden="true"></span> Error
|
||||
</NavLink>
|
||||
</li>
|
||||
<li class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="links">
|
||||
<span class="oi oi-list-rich" aria-hidden="true"></span> Links
|
||||
</NavLink>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -41,10 +41,8 @@
|
|||
"dist/**/*",
|
||||
"src/**/*"
|
||||
],
|
||||
"peerDependencies": {
|
||||
"@aspnet/signalr": "^1.0.0-preview3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aspnet/signalr": "link:../signalr",
|
||||
"msgpack5": "^4.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@
|
|||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@aspnet/signalr@link:../signalr":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
"@types/bl@*":
|
||||
version "0.8.31"
|
||||
resolved "https://registry.yarnpkg.com/@types/bl/-/bl-0.8.31.tgz#caa006702e13c36cda00345fa698b8d55c03113b"
|
||||
|
|
@ -21,11 +25,60 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.5.5.tgz#6f9e8164ae1a55a9beb1d2571cfb7acf9d720c61"
|
||||
integrity sha512-JRnfoh0Ll4ElmIXKxbUfcOodkGvcNHljct6mO1X9hE/mlrMzAx0hYCLAD7sgT53YAY1HdlpzUcV0CkmDqUqTuA==
|
||||
|
||||
ajv@^6.5.5:
|
||||
version "6.10.0"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1"
|
||||
integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==
|
||||
dependencies:
|
||||
fast-deep-equal "^2.0.1"
|
||||
fast-json-stable-stringify "^2.0.0"
|
||||
json-schema-traverse "^0.4.1"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
asn1@~0.2.3:
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
|
||||
integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
|
||||
dependencies:
|
||||
safer-buffer "~2.1.0"
|
||||
|
||||
assert-plus@1.0.0, assert-plus@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
|
||||
integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
|
||||
|
||||
async-limiter@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8"
|
||||
integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==
|
||||
|
||||
asynckit@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
|
||||
|
||||
aws-sign2@~0.7.0:
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
|
||||
integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
|
||||
|
||||
aws4@^1.8.0:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f"
|
||||
integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==
|
||||
|
||||
base64-js@^1.0.2:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886"
|
||||
integrity sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==
|
||||
|
||||
bcrypt-pbkdf@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
|
||||
integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
|
||||
dependencies:
|
||||
tweetnacl "^0.14.3"
|
||||
|
||||
bl@^1.2.1:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c"
|
||||
|
|
@ -42,11 +95,118 @@ buffer@^5.0.8:
|
|||
base64-js "^1.0.2"
|
||||
ieee754 "^1.1.4"
|
||||
|
||||
core-util-is@~1.0.0:
|
||||
caseless@~0.12.0:
|
||||
version "0.12.0"
|
||||
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
|
||||
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
|
||||
|
||||
combined-stream@^1.0.6, combined-stream@~1.0.6:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
||||
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
|
||||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
core-util-is@1.0.2, core-util-is@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||
|
||||
dashdash@^1.12.0:
|
||||
version "1.14.1"
|
||||
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
|
||||
integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
|
||||
dependencies:
|
||||
assert-plus "^1.0.0"
|
||||
|
||||
delayed-stream@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
|
||||
|
||||
ecc-jsbn@~0.1.1:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
|
||||
integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
|
||||
dependencies:
|
||||
jsbn "~0.1.0"
|
||||
safer-buffer "^2.1.0"
|
||||
|
||||
eventsource@^1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.0.7.tgz#8fbc72c93fcd34088090bc0a4e64f4b5cee6d8d0"
|
||||
integrity sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==
|
||||
dependencies:
|
||||
original "^1.0.0"
|
||||
|
||||
extend@~3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
|
||||
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
|
||||
|
||||
extsprintf@1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
|
||||
integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
|
||||
|
||||
extsprintf@^1.2.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
|
||||
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
|
||||
|
||||
fast-deep-equal@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
|
||||
integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=
|
||||
|
||||
fast-json-stable-stringify@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
|
||||
integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I=
|
||||
|
||||
forever-agent@~0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
|
||||
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
|
||||
|
||||
form-data@~2.3.2:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
|
||||
integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
|
||||
dependencies:
|
||||
asynckit "^0.4.0"
|
||||
combined-stream "^1.0.6"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
getpass@^0.1.1:
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
|
||||
integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
|
||||
dependencies:
|
||||
assert-plus "^1.0.0"
|
||||
|
||||
har-schema@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
|
||||
integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
|
||||
|
||||
har-validator@~5.1.0:
|
||||
version "5.1.3"
|
||||
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080"
|
||||
integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==
|
||||
dependencies:
|
||||
ajv "^6.5.5"
|
||||
har-schema "^2.0.0"
|
||||
|
||||
http-signature@~1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
|
||||
integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
|
||||
dependencies:
|
||||
assert-plus "^1.0.0"
|
||||
jsprim "^1.2.2"
|
||||
sshpk "^1.7.0"
|
||||
|
||||
ieee754@^1.1.4:
|
||||
version "1.1.8"
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
|
||||
|
|
@ -57,11 +217,63 @@ inherits@^2.0.3, inherits@~2.0.3:
|
|||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
||||
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
|
||||
|
||||
is-typedarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
|
||||
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
|
||||
|
||||
isarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
|
||||
|
||||
isstream@~0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
|
||||
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
|
||||
|
||||
jsbn@~0.1.0:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
|
||||
integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
|
||||
|
||||
json-schema-traverse@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
|
||||
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
|
||||
|
||||
json-schema@0.2.3:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
|
||||
integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
|
||||
|
||||
json-stringify-safe@~5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
|
||||
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
|
||||
|
||||
jsprim@^1.2.2:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
|
||||
integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
|
||||
dependencies:
|
||||
assert-plus "1.0.0"
|
||||
extsprintf "1.3.0"
|
||||
json-schema "0.2.3"
|
||||
verror "1.10.0"
|
||||
|
||||
mime-db@1.40.0:
|
||||
version "1.40.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32"
|
||||
integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==
|
||||
|
||||
mime-types@^2.1.12, mime-types@~2.1.19:
|
||||
version "2.1.24"
|
||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81"
|
||||
integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==
|
||||
dependencies:
|
||||
mime-db "1.40.0"
|
||||
|
||||
msgpack5@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/msgpack5/-/msgpack5-4.0.2.tgz#88be70e432d142b7a379bfb170f433bd41447508"
|
||||
|
|
@ -72,11 +284,53 @@ msgpack5@^4.0.2:
|
|||
readable-stream "^2.3.3"
|
||||
safe-buffer "^5.1.1"
|
||||
|
||||
oauth-sign@~0.9.0:
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
||||
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
|
||||
|
||||
original@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f"
|
||||
integrity sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==
|
||||
dependencies:
|
||||
url-parse "^1.4.3"
|
||||
|
||||
performance-now@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
||||
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
|
||||
|
||||
process-nextick-args@~2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
|
||||
integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==
|
||||
|
||||
psl@^1.1.24:
|
||||
version "1.1.31"
|
||||
resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184"
|
||||
integrity sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==
|
||||
|
||||
punycode@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
|
||||
integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
|
||||
|
||||
punycode@^2.1.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||
|
||||
qs@~6.5.2:
|
||||
version "6.5.2"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
|
||||
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
|
||||
|
||||
querystringify@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e"
|
||||
integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==
|
||||
|
||||
readable-stream@^2.3.3, readable-stream@^2.3.5:
|
||||
version "2.3.6"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
|
||||
|
|
@ -90,11 +344,67 @@ readable-stream@^2.3.3, readable-stream@^2.3.5:
|
|||
string_decoder "~1.1.1"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
request@^2.88.0:
|
||||
version "2.88.0"
|
||||
resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
|
||||
integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==
|
||||
dependencies:
|
||||
aws-sign2 "~0.7.0"
|
||||
aws4 "^1.8.0"
|
||||
caseless "~0.12.0"
|
||||
combined-stream "~1.0.6"
|
||||
extend "~3.0.2"
|
||||
forever-agent "~0.6.1"
|
||||
form-data "~2.3.2"
|
||||
har-validator "~5.1.0"
|
||||
http-signature "~1.2.0"
|
||||
is-typedarray "~1.0.0"
|
||||
isstream "~0.1.2"
|
||||
json-stringify-safe "~5.0.1"
|
||||
mime-types "~2.1.19"
|
||||
oauth-sign "~0.9.0"
|
||||
performance-now "^2.1.0"
|
||||
qs "~6.5.2"
|
||||
safe-buffer "^5.1.2"
|
||||
tough-cookie "~2.4.3"
|
||||
tunnel-agent "^0.6.0"
|
||||
uuid "^3.3.2"
|
||||
|
||||
requires-port@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
||||
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
|
||||
|
||||
safe-buffer@^5.0.1, safe-buffer@^5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||
|
||||
safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
|
||||
integrity sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==
|
||||
|
||||
safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||
|
||||
sshpk@^1.7.0:
|
||||
version "1.16.1"
|
||||
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
|
||||
integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
|
||||
dependencies:
|
||||
asn1 "~0.2.3"
|
||||
assert-plus "^1.0.0"
|
||||
bcrypt-pbkdf "^1.0.0"
|
||||
dashdash "^1.12.0"
|
||||
ecc-jsbn "~0.1.1"
|
||||
getpass "^0.1.1"
|
||||
jsbn "~0.1.0"
|
||||
safer-buffer "^2.0.2"
|
||||
tweetnacl "~0.14.0"
|
||||
|
||||
string_decoder@~1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
|
||||
|
|
@ -102,7 +412,63 @@ string_decoder@~1.1.1:
|
|||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
tough-cookie@~2.4.3:
|
||||
version "2.4.3"
|
||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781"
|
||||
integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==
|
||||
dependencies:
|
||||
psl "^1.1.24"
|
||||
punycode "^1.4.1"
|
||||
|
||||
tunnel-agent@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
|
||||
integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=
|
||||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
|
||||
version "0.14.5"
|
||||
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
|
||||
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
|
||||
|
||||
uri-js@^4.2.2:
|
||||
version "4.2.2"
|
||||
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
|
||||
integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==
|
||||
dependencies:
|
||||
punycode "^2.1.0"
|
||||
|
||||
url-parse@^1.4.3:
|
||||
version "1.4.7"
|
||||
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278"
|
||||
integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==
|
||||
dependencies:
|
||||
querystringify "^2.1.1"
|
||||
requires-port "^1.0.0"
|
||||
|
||||
util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||
|
||||
uuid@^3.3.2:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
|
||||
integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==
|
||||
|
||||
verror@1.10.0:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
|
||||
integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
|
||||
dependencies:
|
||||
assert-plus "^1.0.0"
|
||||
core-util-is "1.0.2"
|
||||
extsprintf "^1.2.0"
|
||||
|
||||
ws@^6.0.0:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb"
|
||||
integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==
|
||||
dependencies:
|
||||
async-limiter "~1.0.0"
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
],
|
||||
"devDependencies": {
|
||||
"@types/eventsource": "^1.0.2",
|
||||
"@types/jest": "^23.3.2",
|
||||
"@types/node": "^10.9.4",
|
||||
"@types/request": "^2.47.1",
|
||||
"es6-promise": "^4.2.2"
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ export class HttpConnection implements IConnection {
|
|||
private stopPromiseResolver!: (value?: PromiseLike<void>) => void;
|
||||
private stopError?: Error;
|
||||
private accessTokenFactory?: () => string | Promise<string>;
|
||||
private sendQueue?: TransportSendQueue;
|
||||
|
||||
public readonly features: any = {};
|
||||
public connectionId?: string;
|
||||
|
|
@ -146,8 +147,12 @@ export class HttpConnection implements IConnection {
|
|||
return Promise.reject(new Error("Cannot send data if the connection is not in the 'Connected' State."));
|
||||
}
|
||||
|
||||
if (!this.sendQueue) {
|
||||
this.sendQueue = new TransportSendQueue(this.transport!);
|
||||
}
|
||||
|
||||
// Transport will not be null if state is connected
|
||||
return this.transport!.send(data);
|
||||
return this.sendQueue.send(data);
|
||||
}
|
||||
|
||||
public async stop(error?: Error): Promise<void> {
|
||||
|
|
@ -185,6 +190,15 @@ export class HttpConnection implements IConnection {
|
|||
// This exception is returned to the user as a rejected Promise from the start method.
|
||||
}
|
||||
|
||||
if (this.sendQueue) {
|
||||
try {
|
||||
await this.sendQueue.stop();
|
||||
} catch (e) {
|
||||
this.logger.log(LogLevel.Error, `TransportSendQueue.stop() threw error '${e}'.`);
|
||||
}
|
||||
this.sendQueue = undefined;
|
||||
}
|
||||
|
||||
// The transport's onclose will trigger stopConnection which will run our onclose event.
|
||||
// The transport should always be set if currently connected. If it wasn't set, it's likely because
|
||||
// stop was called during start() and start() failed.
|
||||
|
|
@ -501,3 +515,103 @@ export class HttpConnection implements IConnection {
|
|||
function transportMatches(requestedTransport: HttpTransportType | undefined, actualTransport: HttpTransportType) {
|
||||
return !requestedTransport || ((actualTransport & requestedTransport) !== 0);
|
||||
}
|
||||
|
||||
export class TransportSendQueue {
|
||||
private buffer: any[] = [];
|
||||
private sendBufferedData: PromiseSource;
|
||||
private executing: boolean = true;
|
||||
private transportResult?: PromiseSource;
|
||||
private sendLoopPromise: Promise<void>;
|
||||
|
||||
constructor(private readonly transport: ITransport) {
|
||||
this.sendBufferedData = new PromiseSource();
|
||||
this.transportResult = new PromiseSource();
|
||||
|
||||
this.sendLoopPromise = this.sendLoop();
|
||||
}
|
||||
|
||||
public send(data: string | ArrayBuffer): Promise<void> {
|
||||
this.bufferData(data);
|
||||
if (!this.transportResult) {
|
||||
this.transportResult = new PromiseSource();
|
||||
}
|
||||
return this.transportResult.promise;
|
||||
}
|
||||
|
||||
public stop(): Promise<void> {
|
||||
this.executing = false;
|
||||
this.sendBufferedData.resolve();
|
||||
return this.sendLoopPromise;
|
||||
}
|
||||
|
||||
private bufferData(data: string | ArrayBuffer): void {
|
||||
if (this.buffer.length && typeof(this.buffer[0]) !== typeof(data)) {
|
||||
throw new Error(`Expected data to be of type ${typeof(this.buffer)} but was of type ${typeof(data)}`);
|
||||
}
|
||||
|
||||
this.buffer.push(data);
|
||||
this.sendBufferedData.resolve();
|
||||
}
|
||||
|
||||
private async sendLoop(): Promise<void> {
|
||||
while (true) {
|
||||
await this.sendBufferedData.promise;
|
||||
|
||||
if (!this.executing) {
|
||||
if (this.transportResult) {
|
||||
this.transportResult.reject("Connection stopped.");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
this.sendBufferedData = new PromiseSource();
|
||||
|
||||
const transportResult = this.transportResult!;
|
||||
this.transportResult = undefined;
|
||||
|
||||
const data = typeof(this.buffer[0]) === "string" ?
|
||||
this.buffer.join("") :
|
||||
TransportSendQueue.concatBuffers(this.buffer);
|
||||
|
||||
this.buffer.length = 0;
|
||||
|
||||
try {
|
||||
await this.transport.send(data);
|
||||
transportResult.resolve();
|
||||
} catch (error) {
|
||||
transportResult.reject(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static concatBuffers(arrayBuffers: ArrayBuffer[]): ArrayBuffer {
|
||||
const totalLength = arrayBuffers.map((b) => b.byteLength).reduce((a, b) => a + b);
|
||||
const result = new Uint8Array(totalLength);
|
||||
let offset = 0;
|
||||
for (const item of arrayBuffers) {
|
||||
result.set(new Uint8Array(item), offset);
|
||||
offset += item.byteLength;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
class PromiseSource {
|
||||
private resolver?: () => void;
|
||||
private rejecter!: (reason?: any) => void;
|
||||
public promise: Promise<void>;
|
||||
|
||||
constructor() {
|
||||
this.promise = new Promise((resolve, reject) => [this.resolver, this.rejecter] = [resolve, reject]);
|
||||
}
|
||||
|
||||
public resolve(): void {
|
||||
this.resolver!();
|
||||
}
|
||||
|
||||
public reject(reason?: any): void {
|
||||
this.rejecter!(reason);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -860,7 +860,7 @@ export class HubConnection {
|
|||
|
||||
private isObservable(arg: any): arg is IStreamResult<any> {
|
||||
// This allows other stream implementations to just work (like rxjs)
|
||||
return arg.subscribe && typeof arg.subscribe === "function";
|
||||
return arg && arg.subscribe && typeof arg.subscribe === "function";
|
||||
}
|
||||
|
||||
private createStreamInvocation(methodName: string, args: any[], streamIds: string[]): StreamInvocationMessage {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
import { HttpResponse } from "../src/HttpClient";
|
||||
import { HttpConnection, INegotiateResponse } from "../src/HttpConnection";
|
||||
import { HttpConnection, INegotiateResponse, TransportSendQueue } from "../src/HttpConnection";
|
||||
import { IHttpConnectionOptions } from "../src/IHttpConnectionOptions";
|
||||
import { HttpTransportType, ITransport, TransferFormat } from "../src/ITransport";
|
||||
|
||||
|
|
@ -12,6 +12,7 @@ import { EventSourceConstructor, WebSocketConstructor } from "../src/Polyfills";
|
|||
|
||||
import { eachEndpointUrl, eachTransport, VerifyLogger } from "./Common";
|
||||
import { TestHttpClient } from "./TestHttpClient";
|
||||
import { TestTransport } from "./TestTransport";
|
||||
import { PromiseSource, registerUnhandledRejectionHandler, SyncPoint } from "./Utils";
|
||||
|
||||
const commonOptions: IHttpConnectionOptions = {
|
||||
|
|
@ -844,3 +845,232 @@ describe("HttpConnection", () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("TransportSendQueue", () => {
|
||||
it("sends data when not currently sending", async () => {
|
||||
const sendMock = jest.fn(() => Promise.resolve());
|
||||
const transport = new TestTransport();
|
||||
transport.send = sendMock;
|
||||
const queue = new TransportSendQueue(transport);
|
||||
|
||||
const x = queue.send("Hello");
|
||||
await x;
|
||||
|
||||
expect(sendMock.mock.calls.length).toBe(1);
|
||||
|
||||
const stop = queue.stop();
|
||||
await stop;
|
||||
});
|
||||
|
||||
it("sends buffered data on fail", async () => {
|
||||
const promiseSource1 = new PromiseSource();
|
||||
const promiseSource2 = new PromiseSource();
|
||||
const promiseSource3 = new PromiseSource();
|
||||
const transport = new TestTransport();
|
||||
const sendMock = jest.fn()
|
||||
.mockImplementationOnce(async () => {
|
||||
await promiseSource1;
|
||||
promiseSource2.resolve();
|
||||
await promiseSource3;
|
||||
})
|
||||
.mockImplementationOnce(() => Promise.resolve());
|
||||
transport.send = sendMock;
|
||||
|
||||
const queue = new TransportSendQueue(transport);
|
||||
|
||||
const first = queue.send("Hello");
|
||||
// This should allow first to enter transport.send
|
||||
promiseSource1.resolve();
|
||||
// Wait until we're inside transport.send
|
||||
await promiseSource2;
|
||||
|
||||
// This should get queued.
|
||||
const second = queue.send("world");
|
||||
|
||||
promiseSource3.reject("Test error");
|
||||
await expect(first).rejects.toBe("Test error");
|
||||
|
||||
await second;
|
||||
|
||||
expect(sendMock.mock.calls.length).toBe(2);
|
||||
expect(sendMock.mock.calls[0][0]).toEqual("Hello");
|
||||
expect(sendMock.mock.calls[1][0]).toEqual("world");
|
||||
|
||||
await queue.stop();
|
||||
});
|
||||
|
||||
it("rejects promise for buffered sends", async () => {
|
||||
const promiseSource1 = new PromiseSource();
|
||||
const promiseSource2 = new PromiseSource();
|
||||
const promiseSource3 = new PromiseSource();
|
||||
const transport = new TestTransport();
|
||||
const sendMock = jest.fn()
|
||||
.mockImplementationOnce(async () => {
|
||||
await promiseSource1;
|
||||
promiseSource2.resolve();
|
||||
await promiseSource3;
|
||||
})
|
||||
.mockImplementationOnce(() => Promise.reject("Test error"));
|
||||
transport.send = sendMock;
|
||||
|
||||
const queue = new TransportSendQueue(transport);
|
||||
|
||||
const first = queue.send("Hello");
|
||||
// This should allow first to enter transport.send
|
||||
promiseSource1.resolve();
|
||||
// Wait until we're inside transport.send
|
||||
await promiseSource2;
|
||||
|
||||
// This should get queued.
|
||||
const second = queue.send("world");
|
||||
|
||||
promiseSource3.resolve();
|
||||
|
||||
await first;
|
||||
await expect(second).rejects.toBeDefined();
|
||||
|
||||
expect(sendMock.mock.calls.length).toBe(2);
|
||||
expect(sendMock.mock.calls[0][0]).toEqual("Hello");
|
||||
expect(sendMock.mock.calls[1][0]).toEqual("world");
|
||||
|
||||
await queue.stop();
|
||||
});
|
||||
|
||||
it ("concatenates string sends", async () => {
|
||||
const promiseSource1 = new PromiseSource();
|
||||
const promiseSource2 = new PromiseSource();
|
||||
const promiseSource3 = new PromiseSource();
|
||||
const transport = new TestTransport();
|
||||
const sendMock = jest.fn()
|
||||
.mockImplementationOnce(async () => {
|
||||
await promiseSource1;
|
||||
promiseSource2.resolve();
|
||||
await promiseSource3;
|
||||
})
|
||||
.mockImplementationOnce(() => Promise.resolve());
|
||||
transport.send = sendMock;
|
||||
|
||||
const queue = new TransportSendQueue(transport);
|
||||
|
||||
const first = queue.send("Hello");
|
||||
// This should allow first to enter transport.send
|
||||
promiseSource1.resolve();
|
||||
// Wait until we're inside transport.send
|
||||
await promiseSource2;
|
||||
|
||||
// These two operations should get queued.
|
||||
const second = queue.send("world");
|
||||
const third = queue.send("!");
|
||||
|
||||
promiseSource3.resolve();
|
||||
|
||||
await Promise.all([first, second, third]);
|
||||
|
||||
expect(sendMock.mock.calls.length).toBe(2);
|
||||
expect(sendMock.mock.calls[0][0]).toEqual("Hello");
|
||||
expect(sendMock.mock.calls[1][0]).toEqual("world!");
|
||||
|
||||
await queue.stop();
|
||||
});
|
||||
|
||||
it ("concatenates buffered ArrayBuffer", async () => {
|
||||
const promiseSource1 = new PromiseSource();
|
||||
const promiseSource2 = new PromiseSource();
|
||||
const promiseSource3 = new PromiseSource();
|
||||
const transport = new TestTransport();
|
||||
const sendMock = jest.fn()
|
||||
.mockImplementationOnce(async () => {
|
||||
await promiseSource1;
|
||||
promiseSource2.resolve();
|
||||
await promiseSource3;
|
||||
})
|
||||
.mockImplementationOnce(() => Promise.resolve());
|
||||
transport.send = sendMock;
|
||||
|
||||
const queue = new TransportSendQueue(transport);
|
||||
|
||||
const first = queue.send(new Uint8Array([4, 5, 6]));
|
||||
// This should allow first to enter transport.send
|
||||
promiseSource1.resolve();
|
||||
// Wait until we're inside transport.send
|
||||
await promiseSource2;
|
||||
|
||||
// These two operations should get queued.
|
||||
const second = queue.send(new Uint8Array([7, 8, 10]));
|
||||
const third = queue.send(new Uint8Array([12, 14]));
|
||||
|
||||
promiseSource3.resolve();
|
||||
|
||||
await Promise.all([first, second, third]);
|
||||
|
||||
expect(sendMock.mock.calls.length).toBe(2);
|
||||
expect(sendMock.mock.calls[0][0]).toEqual(new Uint8Array([4, 5, 6]));
|
||||
expect(sendMock.mock.calls[1][0]).toEqual(new Uint8Array([7, 8, 10, 12, 14]));
|
||||
|
||||
await queue.stop();
|
||||
});
|
||||
|
||||
it ("throws if mixed data is queued", async () => {
|
||||
const promiseSource1 = new PromiseSource();
|
||||
const promiseSource2 = new PromiseSource();
|
||||
const promiseSource3 = new PromiseSource();
|
||||
const transport = new TestTransport();
|
||||
const sendMock = jest.fn()
|
||||
.mockImplementationOnce(async () => {
|
||||
await promiseSource1;
|
||||
promiseSource2.resolve();
|
||||
await promiseSource3;
|
||||
})
|
||||
.mockImplementationOnce(() => Promise.resolve());
|
||||
transport.send = sendMock;
|
||||
|
||||
const queue = new TransportSendQueue(transport);
|
||||
|
||||
const first = queue.send(new Uint8Array([4, 5, 6]));
|
||||
// This should allow first to enter transport.send
|
||||
promiseSource1.resolve();
|
||||
// Wait until we're inside transport.send
|
||||
await promiseSource2;
|
||||
|
||||
// These two operations should get queued.
|
||||
const second = queue.send(new Uint8Array([7, 8, 10]));
|
||||
expect(() => queue.send("A string!")).toThrow();
|
||||
|
||||
promiseSource3.resolve();
|
||||
|
||||
await Promise.all([first, second]);
|
||||
await queue.stop();
|
||||
});
|
||||
|
||||
it ("rejects pending promises on stop", async () => {
|
||||
const promiseSource = new PromiseSource();
|
||||
const transport = new TestTransport();
|
||||
const sendMock = jest.fn()
|
||||
.mockImplementationOnce(async () => {
|
||||
await promiseSource;
|
||||
});
|
||||
transport.send = sendMock;
|
||||
|
||||
const queue = new TransportSendQueue(transport);
|
||||
|
||||
const send = queue.send("Test");
|
||||
await queue.stop();
|
||||
|
||||
await expect(send).rejects.toBe("Connection stopped.");
|
||||
});
|
||||
|
||||
it ("prevents additional sends after stop", async () => {
|
||||
const promiseSource = new PromiseSource();
|
||||
const transport = new TestTransport();
|
||||
const sendMock = jest.fn()
|
||||
.mockImplementationOnce(async () => {
|
||||
await promiseSource;
|
||||
});
|
||||
transport.send = sendMock;
|
||||
|
||||
const queue = new TransportSendQueue(transport);
|
||||
|
||||
await queue.stop();
|
||||
await expect(queue.send("test")).rejects.toBe("Connection stopped.");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -123,6 +123,35 @@ describe("HubConnection", () => {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("works if argument is null", async () => {
|
||||
await VerifyLogger.run(async (logger) => {
|
||||
const connection = new TestConnection();
|
||||
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
try {
|
||||
// We don't actually care to wait for the send.
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
hubConnection.send("testMethod", "arg", null)
|
||||
.catch((_) => { }); // Suppress exception and unhandled promise rejection warning.
|
||||
|
||||
// Verify the message is sent
|
||||
expect(connection.sentData.length).toBe(1);
|
||||
expect(JSON.parse(connection.sentData[0])).toEqual({
|
||||
arguments: [
|
||||
"arg",
|
||||
null,
|
||||
],
|
||||
streamIds: [],
|
||||
target: "testMethod",
|
||||
type: MessageType.Invocation,
|
||||
});
|
||||
} finally {
|
||||
// Close the connection
|
||||
await hubConnection.stop();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("invoke", () => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
import { ITransport } from "signalr/src/ITransport";
|
||||
|
||||
export class TestTransport implements ITransport {
|
||||
public connect() {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public send(): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public stop(): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public onreceive: ((data: string | ArrayBuffer) => void) | null = null;
|
||||
public onclose: ((error?: Error | undefined) => void) | null = null;
|
||||
}
|
||||
|
|
@ -19,6 +19,11 @@
|
|||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/jest@^23.3.2":
|
||||
version "23.3.14"
|
||||
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-23.3.14.tgz#37daaf78069e7948520474c87b80092ea912520a"
|
||||
integrity sha512-Q5hTcfdudEL2yOmluA1zaSyPbzWPmJ3XfSWeP3RyoYvS9hnje1ZyagrZOuQ6+1nQC1Gw+7gap3pLNL3xL6UBug==
|
||||
|
||||
"@types/node@*", "@types/node@^10.9.4":
|
||||
version "10.9.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.9.4.tgz#0f4cb2dc7c1de6096055357f70179043c33e9897"
|
||||
|
|
|
|||
Loading…
Reference in New Issue