diff --git a/Directory.Build.props b/Directory.Build.props
index 7d0c6585..cec8e3da 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -10,9 +10,6 @@
$(MSBuildThisFileDirectory)
$(MSBuildThisFileDirectory)build\Key.snk
true
- Microsoft
- MicrosoftNuGet
- true
true
diff --git a/Directory.Build.targets b/Directory.Build.targets
index 78626b77..7e3f8df9 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -1,10 +1,6 @@
- $(MicrosoftNETCoreApp20PackageVersion)
- $(MicrosoftNETCoreApp21PackageVersion)
- $(MicrosoftNETCoreApp22PackageVersion)
+ $(MicrosoftNETCoreAppPackageVersion)
$(NETStandardLibrary20PackageVersion)
-
- 99.9
diff --git a/LICENSE.txt b/LICENSE.txt
index 7b2956ec..b3b180cd 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,14 +1,201 @@
-Copyright (c) .NET Foundation and Contributors
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
-All rights reserved.
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-Licensed under the Apache License, Version 2.0 (the "License"); you may not use
-this file except in compliance with the License. You may obtain a copy of the
-License at
+ 1. Definitions.
- http://www.apache.org/licenses/LICENSE-2.0
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
-Unless required by applicable law or agreed to in writing, software distributed
-under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-CONDITIONS OF ANY KIND, either express or implied. See the License for the
-specific language governing permissions and limitations under the License.
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright (c) .NET Foundation and Contributors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.md b/README.md
index e70dfdb9..dfa67285 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,9 @@
-# JavaScriptServices
+# JavaScriptServices [Archived]
-AppVeyor: [](https://ci.appveyor.com/project/aspnetci/javascriptservices/branch/dev)
+## IMPORTANT
+
+The features described in this article are obsolete as of ASP.NET Core 3.0. A simpler SPA frameworks integration mechanism is available in the [Microsoft.AspNetCore.SpaServices.Extensions](https://www.nuget.org/packages/Microsoft.AspNetCore.SpaServices.Extensions) NuGet package. For more information, see [[Announcement] Obsoleting Microsoft.AspNetCore.SpaServices and Microsoft.AspNetCore.NodeServices](https://github.com/dotnet/AspNetCore/issues/12890).
-This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo.
## What is this?
@@ -88,9 +89,3 @@ The [`samples` directory](/samples) contains examples of:
* If you're trying to run the Angular "Music Store" sample, then also run `gulp` (which you need to have installed globally). None of the other samples require this.
* Run the application (`dotnet run`)
* Browse to [http://localhost:5000](http://localhost:5000)
-
-## Contributing
-
-If you're interested in contributing to the various packages, samples, and project templates in this repo, that's great!
-
-Before working on a pull request, especially if it's more than a trivial fix (for example, for a typo), it's usually a good idea first to file an issue describing what you're proposing to do and how it will work. Then you can find out if it's likely that such a pull request will be accepted, and how it fits into wider ongoing plans.
diff --git a/build/dependencies.props b/build/dependencies.props
index 967ed8b0..40e13eba 100644
--- a/build/dependencies.props
+++ b/build/dependencies.props
@@ -3,28 +3,28 @@
$(MSBuildAllProjects);$(MSBuildThisFileFullPath)
- 3.0.0-alpha1-20180821.3
- 3.0.0-alpha1-10393
- 3.0.0-alpha1-10393
- 3.0.0-alpha1-10393
- 3.0.0-alpha1-10393
- 3.0.0-alpha1-10393
- 3.0.0-alpha1-10393
- 3.0.0-alpha1-10393
- 3.0.0-alpha1-10393
- 3.0.0-alpha1-10393
- 3.0.0-alpha1-10393
- 3.0.0-alpha1-10393
- 3.0.0-alpha1-10393
- 3.0.0-alpha1-10393
- 3.0.0-alpha1-10393
- 2.0.9
- 2.1.2
- 2.2.0-preview1-26618-02
+ 3.0.0-build-20181114.5
+ 3.0.0-alpha1-10742
+ 3.0.0-alpha1-10742
+ 3.0.0-alpha1-10742
+ 3.0.0-alpha1-10742
+ 3.0.0-alpha1-10742
+ 3.0.0-alpha1-10742
+ 3.0.0-alpha1-10742
+ 3.0.0-alpha1-10742
+ 3.0.0-alpha1-10742
+ 3.0.0-alpha1-10742
+ 3.0.0-preview-181113-11
+ 3.0.0-preview-181113-11
+ 3.0.0-preview-181113-11
+ 3.0.0-preview-181113-11
+ 3.0.0-preview-181113-11
+ 3.0.0-preview1-26907-05
+ 3.0.0-alpha1-10742
2.0.3
11.0.2
- 4.10.0-preview1-26829-04
+ 4.10.0-preview1-26907-04
-
+
diff --git a/build/repo.props b/build/repo.props
index 17a98ac7..4402da1d 100644
--- a/build/repo.props
+++ b/build/repo.props
@@ -8,8 +8,6 @@
-
-
-
+
diff --git a/korebuild-lock.txt b/korebuild-lock.txt
index 767a4717..73613543 100644
--- a/korebuild-lock.txt
+++ b/korebuild-lock.txt
@@ -1,2 +1,2 @@
-version:3.0.0-alpha1-20180821.3
-commithash:0939a90812deb1c604eb9a4768869687495fc1dd
+version:3.0.0-build-20181114.5
+commithash:880e9a204d4ee4a18dfd83c9fb05a192a28bca60
diff --git a/run.sh b/run.sh
index 61f7a533..4c1fed56 100755
--- a/run.sh
+++ b/run.sh
@@ -220,7 +220,7 @@ if [ -f "$config_file" ]; then
config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")"
config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")"
else
- _error "$config_file contains invalid JSON."
+ __error "$config_file contains invalid JSON."
exit 1
fi
elif __machine_has python ; then
@@ -228,7 +228,7 @@ if [ -f "$config_file" ]; then
config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")"
config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")"
else
- _error "$config_file contains invalid JSON."
+ __error "$config_file contains invalid JSON."
exit 1
fi
elif __machine_has python3 ; then
@@ -236,11 +236,11 @@ if [ -f "$config_file" ]; then
config_channel="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")"
config_tools_source="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")"
else
- _error "$config_file contains invalid JSON."
+ __error "$config_file contains invalid JSON."
exit 1
fi
else
- _error 'Missing required command: jq or python. Could not parse the JSON file.'
+ __error 'Missing required command: jq or python. Could not parse the JSON file.'
exit 1
fi
diff --git a/samples/misc/LatencyTest/LatencyTest.csproj b/samples/misc/LatencyTest/LatencyTest.csproj
index c29edd19..c146eb6a 100644
--- a/samples/misc/LatencyTest/LatencyTest.csproj
+++ b/samples/misc/LatencyTest/LatencyTest.csproj
@@ -1,7 +1,7 @@
- netcoreapp2.2;net461
+ netcoreapp3.0
false
exe
@@ -13,6 +13,7 @@
+
diff --git a/samples/misc/NodeServicesExamples/NodeServicesExamples.csproj b/samples/misc/NodeServicesExamples/NodeServicesExamples.csproj
index b80ffecf..874807b9 100644
--- a/samples/misc/NodeServicesExamples/NodeServicesExamples.csproj
+++ b/samples/misc/NodeServicesExamples/NodeServicesExamples.csproj
@@ -1,7 +1,7 @@
- netcoreapp2.2;net461
+ netcoreapp3.0
true
false
@@ -18,6 +18,8 @@
+
+
diff --git a/samples/misc/Webpack/Webpack.csproj b/samples/misc/Webpack/Webpack.csproj
index b80ffecf..874807b9 100644
--- a/samples/misc/Webpack/Webpack.csproj
+++ b/samples/misc/Webpack/Webpack.csproj
@@ -1,7 +1,7 @@
- netcoreapp2.2;net461
+ netcoreapp3.0
true
false
@@ -18,6 +18,8 @@
+
+
diff --git a/scripts/Regenerate-JSFiles.ps1 b/scripts/Regenerate-JSFiles.ps1
new file mode 100644
index 00000000..ef3336c8
--- /dev/null
+++ b/scripts/Regenerate-JSFiles.ps1
@@ -0,0 +1,28 @@
+[cmdletbinding(SupportsShouldProcess = $true)]
+param(
+)
+
+$ErrorActionPreference = 'Stop'
+Set-StrictMode -Version 2
+
+Push-Location "src"
+try {
+ $dirs = Get-ChildItem -Directory
+ foreach($dir in $dirs)
+ {
+ Push-Location $dir
+ try{
+ if(Test-Path -Path "package.json")
+ {
+ npm install
+ npm run build
+ }
+ }
+ finally{
+ Pop-Location
+ }
+ }
+}
+finally {
+ Pop-Location
+}
diff --git a/src/Microsoft.AspNetCore.NodeServices.Sockets/Content/Node/entrypoint-socket.js b/src/Microsoft.AspNetCore.NodeServices.Sockets/Content/Node/entrypoint-socket.js
index 89dafef6..b9550ff8 100644
--- a/src/Microsoft.AspNetCore.NodeServices.Sockets/Content/Node/entrypoint-socket.js
+++ b/src/Microsoft.AspNetCore.NodeServices.Sockets/Content/Node/entrypoint-socket.js
@@ -1,4 +1,4 @@
-(function(e, a) { for(var i in a) e[i] = a[i]; }(exports, /******/ (function(modules) { // webpackBootstrap
+(function (e, a) { for (var i in a) e[i] = a[i]; }(exports, /******/(function (modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
@@ -6,15 +6,17 @@
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
-/******/ if(installedModules[moduleId]) {
+/******/ if (installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
-/******/ }
+ /******/
+ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
-/******/ };
+ /******/
+ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
@@ -24,7 +26,8 @@
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
-/******/ }
+ /******/
+ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
@@ -34,47 +37,53 @@
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
-/******/ __webpack_require__.d = function(exports, name, getter) {
-/******/ if(!__webpack_require__.o(exports, name)) {
+/******/ __webpack_require__.d = function (exports, name, getter) {
+/******/ if (!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
-/******/ }
-/******/ };
+ /******/
+ }
+ /******/
+ };
/******/
/******/ // define __esModule on exports
-/******/ __webpack_require__.r = function(exports) {
-/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ __webpack_require__.r = function (exports) {
+/******/ if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
-/******/ }
+ /******/
+ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
-/******/ };
+ /******/
+ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
-/******/ __webpack_require__.t = function(value, mode) {
-/******/ if(mode & 1) value = __webpack_require__(value);
-/******/ if(mode & 8) return value;
-/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ __webpack_require__.t = function (value, mode) {
+/******/ if (mode & 1) value = __webpack_require__(value);
+/******/ if (mode & 8) return value;
+/******/ if ((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
-/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ if (mode & 2 && typeof value != 'string') for (var key in value) __webpack_require__.d(ns, key, function (key) { return value[key]; }.bind(null, key));
/******/ return ns;
-/******/ };
+ /******/
+ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
-/******/ __webpack_require__.n = function(module) {
+/******/ __webpack_require__.n = function (module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
-/******/ };
+ /******/
+ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
-/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/ __webpack_require__.o = function (object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
@@ -82,523 +91,536 @@
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
-/******/ })
+ /******/
+})
/************************************************************************/
-/******/ ([
+/******/([
/* 0 */
-/***/ (function(module, exports, __webpack_require__) {
+/***/ (function (module, exports, __webpack_require__) {
-module.exports = __webpack_require__(1);
+ module.exports = __webpack_require__(1);
-/***/ }),
+ /***/
+ }),
/* 1 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-exports.__esModule = true;
-// Limit dependencies to core Node modules. This means the code in this file has to be very low-level and unattractive,
-// but simplifies things for the consumer of this module.
-__webpack_require__(2);
-var net = __webpack_require__(3);
-var path = __webpack_require__(4);
-var readline = __webpack_require__(5);
-var ArgsUtil_1 = __webpack_require__(6);
-var ExitWhenParentExits_1 = __webpack_require__(7);
-var virtualConnectionServer = __webpack_require__(8);
-// Webpack doesn't support dynamic requires for files not present at compile time, so grab a direct
-// reference to Node's runtime 'require' function.
-var dynamicRequire = eval('require');
-// Signal to the .NET side when we're ready to accept invocations
-var server = net.createServer().on('listening', function () {
- console.log('[Microsoft.AspNetCore.NodeServices:Listening]');
-});
-// Each virtual connection represents a separate invocation
-virtualConnectionServer.createInterface(server).on('connection', function (connection) {
- readline.createInterface(connection, null).on('line', function (line) {
- try {
- // Get a reference to the function to invoke
- var invocation = JSON.parse(line);
- var invokedModule = dynamicRequire(path.resolve(process.cwd(), invocation.moduleName));
- var invokedFunction = invocation.exportedFunctionName ? invokedModule[invocation.exportedFunctionName] : invokedModule;
- // Prepare a callback for accepting non-streamed JSON responses
- var hasInvokedCallback_1 = false;
- var invocationCallback = function (errorValue, successValue) {
- if (hasInvokedCallback_1) {
- throw new Error('Cannot supply more than one result. The callback has already been invoked,'
- + ' or the result stream has already been accessed');
- }
- hasInvokedCallback_1 = true;
- connection.end(JSON.stringify({
- result: successValue,
- errorMessage: errorValue && (errorValue.message || errorValue),
- errorDetails: errorValue && (errorValue.stack || null)
- }));
- };
- // Also support streamed binary responses
- Object.defineProperty(invocationCallback, 'stream', {
- enumerable: true,
- get: function () {
- hasInvokedCallback_1 = true;
- return connection;
- }
+/***/ (function (module, exports, __webpack_require__) {
+
+ "use strict";
+
+ exports.__esModule = true;
+ // Limit dependencies to core Node modules. This means the code in this file has to be very low-level and unattractive,
+ // but simplifies things for the consumer of this module.
+ __webpack_require__(2);
+ var net = __webpack_require__(3);
+ var path = __webpack_require__(4);
+ var readline = __webpack_require__(5);
+ var ArgsUtil_1 = __webpack_require__(6);
+ var ExitWhenParentExits_1 = __webpack_require__(7);
+ var virtualConnectionServer = __webpack_require__(8);
+ // Webpack doesn't support dynamic requires for files not present at compile time, so grab a direct
+ // reference to Node's runtime 'require' function.
+ var dynamicRequire = eval('require');
+ // Signal to the .NET side when we're ready to accept invocations
+ var server = net.createServer().on('listening', function () {
+ console.log('[Microsoft.AspNetCore.NodeServices:Listening]');
});
- // Actually invoke it, passing through any supplied args
- invokedFunction.apply(null, [invocationCallback].concat(invocation.args));
- }
- catch (ex) {
- connection.end(JSON.stringify({
- errorMessage: ex.message,
- errorDetails: ex.stack
- }));
- }
- });
-});
-// Begin listening now. The underlying transport varies according to the runtime platform.
-// On Windows it's Named Pipes; on Linux/OSX it's Domain Sockets.
-var useWindowsNamedPipes = /^win/.test(process.platform);
-var parsedArgs = ArgsUtil_1.parseArgs(process.argv);
-var listenAddress = (useWindowsNamedPipes ? '\\\\.\\pipe\\' : '/tmp/') + parsedArgs.listenAddress;
-server.listen(listenAddress);
-ExitWhenParentExits_1.exitWhenParentExits(parseInt(parsedArgs.parentPid), /* ignoreSigint */ true);
-
-
-/***/ }),
+ // Each virtual connection represents a separate invocation
+ virtualConnectionServer.createInterface(server).on('connection', function (connection) {
+ readline.createInterface(connection, null).on('line', function (line) {
+ try {
+ // Get a reference to the function to invoke
+ var invocation = JSON.parse(line);
+ var invokedModule = dynamicRequire(path.resolve(process.cwd(), invocation.moduleName));
+ var invokedFunction = invocation.exportedFunctionName ? invokedModule[invocation.exportedFunctionName] : invokedModule;
+ // Prepare a callback for accepting non-streamed JSON responses
+ var hasInvokedCallback_1 = false;
+ var invocationCallback = function (errorValue, successValue) {
+ if (hasInvokedCallback_1) {
+ throw new Error('Cannot supply more than one result. The callback has already been invoked,'
+ + ' or the result stream has already been accessed');
+ }
+ hasInvokedCallback_1 = true;
+ connection.end(JSON.stringify({
+ result: successValue,
+ errorMessage: errorValue && (errorValue.message || errorValue),
+ errorDetails: errorValue && (errorValue.stack || null)
+ }));
+ };
+ // Also support streamed binary responses
+ Object.defineProperty(invocationCallback, 'stream', {
+ enumerable: true,
+ get: function () {
+ hasInvokedCallback_1 = true;
+ return connection;
+ }
+ });
+ // Actually invoke it, passing through any supplied args
+ invokedFunction.apply(null, [invocationCallback].concat(invocation.args));
+ }
+ catch (ex) {
+ connection.end(JSON.stringify({
+ errorMessage: ex.message,
+ errorDetails: ex.stack
+ }));
+ }
+ });
+ });
+ // Begin listening now. The underlying transport varies according to the runtime platform.
+ // On Windows it's Named Pipes; on Linux/OSX it's Domain Sockets.
+ var useWindowsNamedPipes = /^win/.test(process.platform);
+ var parsedArgs = ArgsUtil_1.parseArgs(process.argv);
+ var listenAddress = (useWindowsNamedPipes ? '\\\\.\\pipe\\' : '/tmp/') + parsedArgs.listenAddress;
+ server.listen(listenAddress);
+ ExitWhenParentExits_1.exitWhenParentExits(parseInt(parsedArgs.parentPid), /* ignoreSigint */ true);
+
+
+ /***/
+ }),
/* 2 */
-/***/ (function(module, exports) {
-
-// When Node writes to stdout/strerr, we capture that and convert the lines into calls on the
-// active .NET ILogger. But by default, stdout/stderr don't have any way of distinguishing
-// linebreaks inside log messages from the linebreaks that delimit separate log messages,
-// so multiline strings will end up being written to the ILogger as multiple independent
-// log messages. This makes them very hard to make sense of, especially when they represent
-// something like stack traces.
-//
-// To fix this, we intercept stdout/stderr writes, and replace internal linebreaks with a
-// marker token. When .NET receives the lines, it converts the marker tokens back to regular
-// linebreaks within the logged messages.
-//
-// Note that it's better to do the interception at the stdout/stderr level, rather than at
-// the console.log/console.error (etc.) level, because this takes place after any native
-// message formatting has taken place (e.g., inserting values for % placeholders).
-var findInternalNewlinesRegex = /\n(?!$)/g;
-var encodedNewline = '__ns_newline__';
-encodeNewlinesWrittenToStream(process.stdout);
-encodeNewlinesWrittenToStream(process.stderr);
-function encodeNewlinesWrittenToStream(outputStream) {
- var origWriteFunction = outputStream.write;
- outputStream.write = function (value) {
- // Only interfere with the write if it's definitely a string
- if (typeof value === 'string') {
- var argsClone = Array.prototype.slice.call(arguments, 0);
- argsClone[0] = encodeNewlinesInString(value);
- origWriteFunction.apply(this, argsClone);
- }
- else {
- origWriteFunction.apply(this, arguments);
- }
- };
-}
-function encodeNewlinesInString(str) {
- return str.replace(findInternalNewlinesRegex, encodedNewline);
-}
+/***/ (function (module, exports) {
+
+ // When Node writes to stdout/strerr, we capture that and convert the lines into calls on the
+ // active .NET ILogger. But by default, stdout/stderr don't have any way of distinguishing
+ // linebreaks inside log messages from the linebreaks that delimit separate log messages,
+ // so multiline strings will end up being written to the ILogger as multiple independent
+ // log messages. This makes them very hard to make sense of, especially when they represent
+ // something like stack traces.
+ //
+ // To fix this, we intercept stdout/stderr writes, and replace internal linebreaks with a
+ // marker token. When .NET receives the lines, it converts the marker tokens back to regular
+ // linebreaks within the logged messages.
+ //
+ // Note that it's better to do the interception at the stdout/stderr level, rather than at
+ // the console.log/console.error (etc.) level, because this takes place after any native
+ // message formatting has taken place (e.g., inserting values for % placeholders).
+ var findInternalNewlinesRegex = /\n(?!$)/g;
+ var encodedNewline = '__ns_newline__';
+ encodeNewlinesWrittenToStream(process.stdout);
+ encodeNewlinesWrittenToStream(process.stderr);
+ function encodeNewlinesWrittenToStream(outputStream) {
+ var origWriteFunction = outputStream.write;
+ outputStream.write = function (value) {
+ // Only interfere with the write if it's definitely a string
+ if (typeof value === 'string') {
+ var argsClone = Array.prototype.slice.call(arguments, 0);
+ argsClone[0] = encodeNewlinesInString(value);
+ origWriteFunction.apply(this, argsClone);
+ }
+ else {
+ origWriteFunction.apply(this, arguments);
+ }
+ };
+ }
+ function encodeNewlinesInString(str) {
+ return str.replace(findInternalNewlinesRegex, encodedNewline);
+ }
-/***/ }),
+ /***/
+ }),
/* 3 */
-/***/ (function(module, exports) {
+/***/ (function (module, exports) {
-module.exports = require("net");
+ module.exports = require("net");
-/***/ }),
+ /***/
+ }),
/* 4 */
-/***/ (function(module, exports) {
+/***/ (function (module, exports) {
-module.exports = require("path");
+ module.exports = require("path");
-/***/ }),
+ /***/
+ }),
/* 5 */
-/***/ (function(module, exports) {
+/***/ (function (module, exports) {
-module.exports = require("readline");
+ module.exports = require("readline");
-/***/ }),
+ /***/
+ }),
/* 6 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-exports.__esModule = true;
-function parseArgs(args) {
- // Very simplistic parsing which is sufficient for the cases needed. We don't want to bring in any external
- // dependencies (such as an args-parsing library) to this file.
- var result = {};
- var currentKey = null;
- args.forEach(function (arg) {
- if (arg.indexOf('--') === 0) {
- var argName = arg.substring(2);
- result[argName] = undefined;
- currentKey = argName;
- }
- else if (currentKey) {
- result[currentKey] = arg;
- currentKey = null;
- }
- });
- return result;
-}
-exports.parseArgs = parseArgs;
+/***/ (function (module, exports, __webpack_require__) {
+
+ "use strict";
+
+ exports.__esModule = true;
+ function parseArgs(args) {
+ // Very simplistic parsing which is sufficient for the cases needed. We don't want to bring in any external
+ // dependencies (such as an args-parsing library) to this file.
+ var result = {};
+ var currentKey = null;
+ args.forEach(function (arg) {
+ if (arg.indexOf('--') === 0) {
+ var argName = arg.substring(2);
+ result[argName] = undefined;
+ currentKey = argName;
+ }
+ else if (currentKey) {
+ result[currentKey] = arg;
+ currentKey = null;
+ }
+ });
+ return result;
+ }
+ exports.parseArgs = parseArgs;
-/***/ }),
+ /***/
+ }),
/* 7 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-/*
-In general, we want the Node child processes to be terminated as soon as the parent .NET processes exit,
-because we have no further use for them. If the .NET process shuts down gracefully, it will run its
-finalizers, one of which (in OutOfProcessNodeInstance.cs) will kill its associated Node process immediately.
-
-But if the .NET process is terminated forcefully (e.g., on Linux/OSX with 'kill -9'), then it won't have
-any opportunity to shut down its child processes, and by default they will keep running. In this case, it's
-up to the child process to detect this has happened and terminate itself.
-
-There are many possible approaches to detecting when a parent process has exited, most of which behave
-differently between Windows and Linux/OS X:
-
- - On Windows, the parent process can mark its child as being a 'job' that should auto-terminate when
- the parent does (http://stackoverflow.com/a/4657392). Not cross-platform.
- - The child Node process can get a callback when the parent disconnects (process.on('disconnect', ...)).
- But despite http://stackoverflow.com/a/16487966, no callback fires in any case I've tested (Windows / OS X).
- - The child Node process can get a callback when its stdin/stdout are disconnected, as described at
- http://stackoverflow.com/a/15693934. This works well on OS X, but calling stdout.resume() on Windows
- causes the process to terminate prematurely.
- - I don't know why, but on Windows, it's enough to invoke process.stdin.resume(). For some reason this causes
- the child Node process to exit as soon as the parent one does, but I don't see this documented anywhere.
- - You can poll to see if the parent process, or your stdin/stdout connection to it, is gone
- - You can directly pass a parent process PID to the child, and then have the child poll to see if it's
- still running (e.g., using process.kill(pid, 0), which doesn't kill it but just tests whether it exists,
- as per https://nodejs.org/api/process.html#process_process_kill_pid_signal)
- - Or, on each poll, you can try writing to process.stdout. If the parent has died, then this will throw.
- However I don't see this documented anywhere. It would be nice if you could just poll for whether or not
- process.stdout is still connected (without actually writing to it) but I haven't found any property whose
- value changes until you actually try to write to it.
-
-Of these, the only cross-platform approach that is actually documented as a valid strategy is simply polling
-to check whether the parent PID is still running. So that's what we do here.
-*/
-exports.__esModule = true;
-var pollIntervalMs = 1000;
-function exitWhenParentExits(parentPid, ignoreSigint) {
- setInterval(function () {
- if (!processExists(parentPid)) {
- // Can't log anything at this point, because out stdout was connected to the parent,
- // but the parent is gone.
- process.exit();
- }
- }, pollIntervalMs);
- if (ignoreSigint) {
- // Pressing ctrl+c in the terminal sends a SIGINT to all processes in the foreground process tree.
- // By default, the Node process would then exit before the .NET process, because ASP.NET implements
- // a delayed shutdown to allow ongoing requests to complete.
- //
- // This is problematic, because if Node exits first, the CopyToAsync code in ConditionalProxyMiddleware
- // will experience a read fault, and logs a huge load of errors. Fortunately, since the Node process is
- // already set up to shut itself down if it detects the .NET process is terminated, all we have to do is
- // ignore the SIGINT. The Node process will then terminate automatically after the .NET process does.
- //
- // A better solution would be to have WebpackDevMiddleware listen for SIGINT and gracefully close any
- // ongoing EventSource connections before letting the Node process exit, independently of the .NET
- // process exiting. However, doing this well in general is very nontrivial (see all the discussion at
- // https://github.com/nodejs/node/issues/2642).
- process.on('SIGINT', function () {
- console.log('Received SIGINT. Waiting for .NET process to exit...');
- });
- }
-}
-exports.exitWhenParentExits = exitWhenParentExits;
-function processExists(pid) {
- try {
- // Sending signal 0 - on all platforms - tests whether the process exists. As long as it doesn't
- // throw, that means it does exist.
- process.kill(pid, 0);
- return true;
- }
- catch (ex) {
- // If the reason for the error is that we don't have permission to ask about this process,
- // report that as a separate problem.
- if (ex.code === 'EPERM') {
- throw new Error("Attempted to check whether process " + pid + " was running, but got a permissions error.");
- }
- return false;
- }
-}
-
-
-/***/ }),
-/* 8 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-exports.__esModule = true;
-var events_1 = __webpack_require__(9);
-var VirtualConnection_1 = __webpack_require__(10);
-// Keep this in sync with the equivalent constant in the .NET code. Both sides split up their transmissions into frames with this max length,
-// and both will reject longer frames.
-var MaxFrameBodyLength = 16 * 1024;
-/**
- * Accepts connections to a net.Server and adapts them to behave as multiplexed connections. That is, for each physical socket connection,
- * we track a list of 'virtual connections' whose API is a Duplex stream. The remote clients may open and close as many virtual connections
- * as they wish, reading and writing to them independently, without the overhead of establishing new physical connections each time.
- */
-function createInterface(server) {
- var emitter = new events_1.EventEmitter();
- server.on('connection', function (socket) {
- // For each physical socket connection, maintain a set of virtual connections. Issue a notification whenever
- // a new virtual connections is opened.
- var childSockets = new VirtualConnectionsCollection(socket, function (virtualConnection) {
- emitter.emit('connection', virtualConnection);
- });
- });
- return emitter;
-}
-exports.createInterface = createInterface;
-/**
- * Tracks the 'virtual connections' associated with a single physical socket connection.
- */
-var VirtualConnectionsCollection = /** @class */ (function () {
- function VirtualConnectionsCollection(_socket, _onVirtualConnectionCallback) {
- var _this = this;
- this._socket = _socket;
- this._onVirtualConnectionCallback = _onVirtualConnectionCallback;
- this._currentFrameHeader = null;
- this._virtualConnections = {};
- // If the remote end closes the physical socket, treat all the virtual connections as being closed remotely too
- this._socket.on('close', function () {
- Object.getOwnPropertyNames(_this._virtualConnections).forEach(function (id) {
- // A 'null' frame signals that the connection was closed remotely
- _this._virtualConnections[id].onReceivedData(null);
- });
- });
- this._socket.on('readable', this._onIncomingDataAvailable.bind(this));
- }
- /**
- * This is called whenever the underlying socket signals that it may have some data available to read. It will synchronously read as many
- * message frames as it can from the underlying socket, opens virtual connections as needed, and dispatches data to them.
- */
- VirtualConnectionsCollection.prototype._onIncomingDataAvailable = function () {
- var exhaustedAllData = false;
- while (!exhaustedAllData) {
- // We might already have a pending frame header from the previous time this method ran, but if not, that's the next thing we need to read
- if (this._currentFrameHeader === null) {
- this._currentFrameHeader = this._readNextFrameHeader();
- }
- if (this._currentFrameHeader === null) {
- // There's not enough data to fill a frameheader, so wait until more arrives later
- // The next attempt to read from the socket will start from the same place this one did (incomplete reads don't consume any data)
- exhaustedAllData = true;
+/***/ (function (module, exports, __webpack_require__) {
+
+ "use strict";
+
+ /*
+ In general, we want the Node child processes to be terminated as soon as the parent .NET processes exit,
+ because we have no further use for them. If the .NET process shuts down gracefully, it will run its
+ finalizers, one of which (in OutOfProcessNodeInstance.cs) will kill its associated Node process immediately.
+
+ But if the .NET process is terminated forcefully (e.g., on Linux/OSX with 'kill -9'), then it won't have
+ any opportunity to shut down its child processes, and by default they will keep running. In this case, it's
+ up to the child process to detect this has happened and terminate itself.
+
+ There are many possible approaches to detecting when a parent process has exited, most of which behave
+ differently between Windows and Linux/OS X:
+
+ - On Windows, the parent process can mark its child as being a 'job' that should auto-terminate when
+ the parent does (http://stackoverflow.com/a/4657392). Not cross-platform.
+ - The child Node process can get a callback when the parent disconnects (process.on('disconnect', ...)).
+ But despite http://stackoverflow.com/a/16487966, no callback fires in any case I've tested (Windows / OS X).
+ - The child Node process can get a callback when its stdin/stdout are disconnected, as described at
+ http://stackoverflow.com/a/15693934. This works well on OS X, but calling stdout.resume() on Windows
+ causes the process to terminate prematurely.
+ - I don't know why, but on Windows, it's enough to invoke process.stdin.resume(). For some reason this causes
+ the child Node process to exit as soon as the parent one does, but I don't see this documented anywhere.
+ - You can poll to see if the parent process, or your stdin/stdout connection to it, is gone
+ - You can directly pass a parent process PID to the child, and then have the child poll to see if it's
+ still running (e.g., using process.kill(pid, 0), which doesn't kill it but just tests whether it exists,
+ as per https://nodejs.org/api/process.html#process_process_kill_pid_signal)
+ - Or, on each poll, you can try writing to process.stdout. If the parent has died, then this will throw.
+ However I don't see this documented anywhere. It would be nice if you could just poll for whether or not
+ process.stdout is still connected (without actually writing to it) but I haven't found any property whose
+ value changes until you actually try to write to it.
+
+ Of these, the only cross-platform approach that is actually documented as a valid strategy is simply polling
+ to check whether the parent PID is still running. So that's what we do here.
+ */
+ exports.__esModule = true;
+ var pollIntervalMs = 1000;
+ function exitWhenParentExits(parentPid, ignoreSigint) {
+ setInterval(function () {
+ if (!processExists(parentPid)) {
+ // Can't log anything at this point, because out stdout was connected to the parent,
+ // but the parent is gone.
+ process.exit();
+ }
+ }, pollIntervalMs);
+ if (ignoreSigint) {
+ // Pressing ctrl+c in the terminal sends a SIGINT to all processes in the foreground process tree.
+ // By default, the Node process would then exit before the .NET process, because ASP.NET implements
+ // a delayed shutdown to allow ongoing requests to complete.
+ //
+ // This is problematic, because if Node exits first, the CopyToAsync code in ConditionalProxyMiddleware
+ // will experience a read fault, and logs a huge load of errors. Fortunately, since the Node process is
+ // already set up to shut itself down if it detects the .NET process is terminated, all we have to do is
+ // ignore the SIGINT. The Node process will then terminate automatically after the .NET process does.
+ //
+ // A better solution would be to have WebpackDevMiddleware listen for SIGINT and gracefully close any
+ // ongoing EventSource connections before letting the Node process exit, independently of the .NET
+ // process exiting. However, doing this well in general is very nontrivial (see all the discussion at
+ // https://github.com/nodejs/node/issues/2642).
+ process.on('SIGINT', function () {
+ console.log('Received SIGINT. Waiting for .NET process to exit...');
+ });
+ }
}
- else {
- var frameBodyLength = this._currentFrameHeader.bodyLength;
- var frameBodyOrNull = frameBodyLength > 0 ? this._socket.read(this._currentFrameHeader.bodyLength) : null;
- if (frameBodyOrNull !== null || frameBodyLength === 0) {
- // We have a complete frame header+body pair, so we can now dispatch this to a virtual connection. We set _currentFrameHeader back to null
- // so that the next thing we try to read is the next frame header.
- var headerCopy = this._currentFrameHeader;
- this._currentFrameHeader = null;
- this._onReceivedCompleteFrame(headerCopy, frameBodyOrNull);
+ exports.exitWhenParentExits = exitWhenParentExits;
+ function processExists(pid) {
+ try {
+ // Sending signal 0 - on all platforms - tests whether the process exists. As long as it doesn't
+ // throw, that means it does exist.
+ process.kill(pid, 0);
+ return true;
}
- else {
- // There's not enough data to fill the pending frame body, so wait until more arrives later
- // The next attempt to read from the socket will start from the same place this one did (incomplete reads don't consume any data)
- exhaustedAllData = true;
+ catch (ex) {
+ // If the reason for the error is that we don't have permission to ask about this process,
+ // report that as a separate problem.
+ if (ex.code === 'EPERM') {
+ throw new Error("Attempted to check whether process " + pid + " was running, but got a permissions error.");
+ }
+ return false;
}
}
- }
- };
- VirtualConnectionsCollection.prototype._onReceivedCompleteFrame = function (header, bodyIfNotEmpty) {
- // An incoming zero-length frame signals that there's no more data to read.
- // Signal this to the Node stream APIs by pushing a 'null' chunk to it.
- var virtualConnection = this._getOrOpenVirtualConnection(header);
- virtualConnection.onReceivedData(header.bodyLength > 0 ? bodyIfNotEmpty : null);
- };
- VirtualConnectionsCollection.prototype._getOrOpenVirtualConnection = function (header) {
- if (this._virtualConnections.hasOwnProperty(header.connectionIdString)) {
- // It's an existing virtual connection
- return this._virtualConnections[header.connectionIdString];
- }
- else {
- // It's a new one
- return this._openVirtualConnection(header);
- }
- };
- VirtualConnectionsCollection.prototype._openVirtualConnection = function (header) {
- var _this = this;
- var beginWriteCallback = function (data, writeCompletedCallback) {
- // Only send nonempty frames, since empty ones are a signal to close the virtual connection
- if (data.length > 0) {
- _this._sendFrame(header.connectionIdBinary, data, writeCompletedCallback);
- }
- };
- var newVirtualConnection = new VirtualConnection_1.VirtualConnection(beginWriteCallback);
- newVirtualConnection.on('end', function () {
- // The virtual connection was closed remotely. Clean up locally.
- _this._onVirtualConnectionWasClosed(header.connectionIdString);
- });
- newVirtualConnection.on('finish', function () {
- // The virtual connection was closed locally. Clean up locally, and notify the remote that we're done.
- _this._onVirtualConnectionWasClosed(header.connectionIdString);
- _this._sendFrame(header.connectionIdBinary, new Buffer(0));
- });
- this._virtualConnections[header.connectionIdString] = newVirtualConnection;
- this._onVirtualConnectionCallback(newVirtualConnection);
- return newVirtualConnection;
- };
- /**
- * Attempts to read a complete frame header, synchronously, from the underlying socket.
- * If not enough data is available synchronously, returns null without consuming any data from the socket.
- */
- VirtualConnectionsCollection.prototype._readNextFrameHeader = function () {
- var headerBuf = this._socket.read(12);
- if (headerBuf !== null) {
- // We have enough data synchronously
- var connectionIdBinary = headerBuf.slice(0, 8);
- var connectionIdString = connectionIdBinary.toString('hex');
- var bodyLength = headerBuf.readInt32LE(8);
- if (bodyLength < 0 || bodyLength > MaxFrameBodyLength) {
- // Throwing here is going to bring down the whole process, so this cannot be allowed to happen in real use.
- // But it won't happen in real use, because this is only used with our .NET client, which doesn't violate this rule.
- throw new Error('Illegal frame body length: ' + bodyLength);
- }
- return { connectionIdBinary: connectionIdBinary, connectionIdString: connectionIdString, bodyLength: bodyLength };
- }
- else {
- // Not enough bytes are available synchronously, so none were consumed
- return null;
- }
- };
- VirtualConnectionsCollection.prototype._sendFrame = function (connectionIdBinary, data, callback) {
- // For all sends other than the last one, only invoke the callback if it failed.
- // Also, only invoke the callback at most once.
- var hasInvokedCallback = false;
- var finalCallback = callback && (function (error) {
- if (!hasInvokedCallback) {
- hasInvokedCallback = true;
- callback(error);
- }
- });
- var notFinalCallback = callback && (function (error) {
- if (error) {
- finalCallback(error);
- }
- });
- // The amount of data we're writing might exceed MaxFrameBodyLength, so split into frames as needed.
- // Note that we always send at least one frame, even if it's empty (because that's the close-virtual-connection signal).
- // If needed, this could be changed to send frames asynchronously, so that large sends could proceed in parallel
- // (though that would involve making a clone of 'data', to avoid the risk of it being mutated during the send).
- var bytesSent = 0;
- do {
- var nextFrameBodyLength = Math.min(MaxFrameBodyLength, data.length - bytesSent);
- var isFinalChunk = (bytesSent + nextFrameBodyLength) === data.length;
- this._socket.write(connectionIdBinary, notFinalCallback);
- this._sendInt32LE(nextFrameBodyLength, notFinalCallback);
- this._socket.write(data.slice(bytesSent, bytesSent + nextFrameBodyLength), isFinalChunk ? finalCallback : notFinalCallback);
- bytesSent += nextFrameBodyLength;
- } while (bytesSent < data.length);
- };
- /**
- * Sends a number serialized in the correct format for .NET to receive as a System.Int32
- */
- VirtualConnectionsCollection.prototype._sendInt32LE = function (value, callback) {
- var buf = new Buffer(4);
- buf.writeInt32LE(value, 0);
- this._socket.write(buf, callback);
- };
- VirtualConnectionsCollection.prototype._onVirtualConnectionWasClosed = function (id) {
- if (this._virtualConnections.hasOwnProperty(id)) {
- delete this._virtualConnections[id];
- }
- };
- return VirtualConnectionsCollection;
-}());
-/***/ }),
+ /***/
+ }),
+/* 8 */
+/***/ (function (module, exports, __webpack_require__) {
+
+ "use strict";
+
+ exports.__esModule = true;
+ var events_1 = __webpack_require__(9);
+ var VirtualConnection_1 = __webpack_require__(10);
+ // Keep this in sync with the equivalent constant in the .NET code. Both sides split up their transmissions into frames with this max length,
+ // and both will reject longer frames.
+ var MaxFrameBodyLength = 16 * 1024;
+ /**
+ * Accepts connections to a net.Server and adapts them to behave as multiplexed connections. That is, for each physical socket connection,
+ * we track a list of 'virtual connections' whose API is a Duplex stream. The remote clients may open and close as many virtual connections
+ * as they wish, reading and writing to them independently, without the overhead of establishing new physical connections each time.
+ */
+ function createInterface(server) {
+ var emitter = new events_1.EventEmitter();
+ server.on('connection', function (socket) {
+ // For each physical socket connection, maintain a set of virtual connections. Issue a notification whenever
+ // a new virtual connections is opened.
+ var childSockets = new VirtualConnectionsCollection(socket, function (virtualConnection) {
+ emitter.emit('connection', virtualConnection);
+ });
+ });
+ return emitter;
+ }
+ exports.createInterface = createInterface;
+ /**
+ * Tracks the 'virtual connections' associated with a single physical socket connection.
+ */
+ var VirtualConnectionsCollection = /** @class */ (function () {
+ function VirtualConnectionsCollection(_socket, _onVirtualConnectionCallback) {
+ var _this = this;
+ this._socket = _socket;
+ this._onVirtualConnectionCallback = _onVirtualConnectionCallback;
+ this._currentFrameHeader = null;
+ this._virtualConnections = {};
+ // If the remote end closes the physical socket, treat all the virtual connections as being closed remotely too
+ this._socket.on('close', function () {
+ Object.getOwnPropertyNames(_this._virtualConnections).forEach(function (id) {
+ // A 'null' frame signals that the connection was closed remotely
+ _this._virtualConnections[id].onReceivedData(null);
+ });
+ });
+ this._socket.on('readable', this._onIncomingDataAvailable.bind(this));
+ }
+ /**
+ * This is called whenever the underlying socket signals that it may have some data available to read. It will synchronously read as many
+ * message frames as it can from the underlying socket, opens virtual connections as needed, and dispatches data to them.
+ */
+ VirtualConnectionsCollection.prototype._onIncomingDataAvailable = function () {
+ var exhaustedAllData = false;
+ while (!exhaustedAllData) {
+ // We might already have a pending frame header from the previous time this method ran, but if not, that's the next thing we need to read
+ if (this._currentFrameHeader === null) {
+ this._currentFrameHeader = this._readNextFrameHeader();
+ }
+ if (this._currentFrameHeader === null) {
+ // There's not enough data to fill a frameheader, so wait until more arrives later
+ // The next attempt to read from the socket will start from the same place this one did (incomplete reads don't consume any data)
+ exhaustedAllData = true;
+ }
+ else {
+ var frameBodyLength = this._currentFrameHeader.bodyLength;
+ var frameBodyOrNull = frameBodyLength > 0 ? this._socket.read(this._currentFrameHeader.bodyLength) : null;
+ if (frameBodyOrNull !== null || frameBodyLength === 0) {
+ // We have a complete frame header+body pair, so we can now dispatch this to a virtual connection. We set _currentFrameHeader back to null
+ // so that the next thing we try to read is the next frame header.
+ var headerCopy = this._currentFrameHeader;
+ this._currentFrameHeader = null;
+ this._onReceivedCompleteFrame(headerCopy, frameBodyOrNull);
+ }
+ else {
+ // There's not enough data to fill the pending frame body, so wait until more arrives later
+ // The next attempt to read from the socket will start from the same place this one did (incomplete reads don't consume any data)
+ exhaustedAllData = true;
+ }
+ }
+ }
+ };
+ VirtualConnectionsCollection.prototype._onReceivedCompleteFrame = function (header, bodyIfNotEmpty) {
+ // An incoming zero-length frame signals that there's no more data to read.
+ // Signal this to the Node stream APIs by pushing a 'null' chunk to it.
+ var virtualConnection = this._getOrOpenVirtualConnection(header);
+ virtualConnection.onReceivedData(header.bodyLength > 0 ? bodyIfNotEmpty : null);
+ };
+ VirtualConnectionsCollection.prototype._getOrOpenVirtualConnection = function (header) {
+ if (this._virtualConnections.hasOwnProperty(header.connectionIdString)) {
+ // It's an existing virtual connection
+ return this._virtualConnections[header.connectionIdString];
+ }
+ else {
+ // It's a new one
+ return this._openVirtualConnection(header);
+ }
+ };
+ VirtualConnectionsCollection.prototype._openVirtualConnection = function (header) {
+ var _this = this;
+ var beginWriteCallback = function (data, writeCompletedCallback) {
+ // Only send nonempty frames, since empty ones are a signal to close the virtual connection
+ if (data.length > 0) {
+ _this._sendFrame(header.connectionIdBinary, data, writeCompletedCallback);
+ }
+ };
+ var newVirtualConnection = new VirtualConnection_1.VirtualConnection(beginWriteCallback);
+ newVirtualConnection.on('end', function () {
+ // The virtual connection was closed remotely. Clean up locally.
+ _this._onVirtualConnectionWasClosed(header.connectionIdString);
+ });
+ newVirtualConnection.on('finish', function () {
+ // The virtual connection was closed locally. Clean up locally, and notify the remote that we're done.
+ _this._onVirtualConnectionWasClosed(header.connectionIdString);
+ _this._sendFrame(header.connectionIdBinary, Buffer.alloc(0));
+ });
+ this._virtualConnections[header.connectionIdString] = newVirtualConnection;
+ this._onVirtualConnectionCallback(newVirtualConnection);
+ return newVirtualConnection;
+ };
+ /**
+ * Attempts to read a complete frame header, synchronously, from the underlying socket.
+ * If not enough data is available synchronously, returns null without consuming any data from the socket.
+ */
+ VirtualConnectionsCollection.prototype._readNextFrameHeader = function () {
+ var headerBuf = this._socket.read(12);
+ if (headerBuf !== null) {
+ // We have enough data synchronously
+ var connectionIdBinary = headerBuf.slice(0, 8);
+ var connectionIdString = connectionIdBinary.toString('hex');
+ var bodyLength = headerBuf.readInt32LE(8);
+ if (bodyLength < 0 || bodyLength > MaxFrameBodyLength) {
+ // Throwing here is going to bring down the whole process, so this cannot be allowed to happen in real use.
+ // But it won't happen in real use, because this is only used with our .NET client, which doesn't violate this rule.
+ throw new Error('Illegal frame body length: ' + bodyLength);
+ }
+ return { connectionIdBinary: connectionIdBinary, connectionIdString: connectionIdString, bodyLength: bodyLength };
+ }
+ else {
+ // Not enough bytes are available synchronously, so none were consumed
+ return null;
+ }
+ };
+ VirtualConnectionsCollection.prototype._sendFrame = function (connectionIdBinary, data, callback) {
+ // For all sends other than the last one, only invoke the callback if it failed.
+ // Also, only invoke the callback at most once.
+ var hasInvokedCallback = false;
+ var finalCallback = callback && (function (error) {
+ if (!hasInvokedCallback) {
+ hasInvokedCallback = true;
+ callback(error);
+ }
+ });
+ var notFinalCallback = callback && (function (error) {
+ if (error) {
+ finalCallback(error);
+ }
+ });
+ // The amount of data we're writing might exceed MaxFrameBodyLength, so split into frames as needed.
+ // Note that we always send at least one frame, even if it's empty (because that's the close-virtual-connection signal).
+ // If needed, this could be changed to send frames asynchronously, so that large sends could proceed in parallel
+ // (though that would involve making a clone of 'data', to avoid the risk of it being mutated during the send).
+ var bytesSent = 0;
+ do {
+ var nextFrameBodyLength = Math.min(MaxFrameBodyLength, data.length - bytesSent);
+ var isFinalChunk = (bytesSent + nextFrameBodyLength) === data.length;
+ this._socket.write(connectionIdBinary, notFinalCallback);
+ this._sendInt32LE(nextFrameBodyLength, notFinalCallback);
+ this._socket.write(data.slice(bytesSent, bytesSent + nextFrameBodyLength), isFinalChunk ? finalCallback : notFinalCallback);
+ bytesSent += nextFrameBodyLength;
+ } while (bytesSent < data.length);
+ };
+ /**
+ * Sends a number serialized in the correct format for .NET to receive as a System.Int32
+ */
+ VirtualConnectionsCollection.prototype._sendInt32LE = function (value, callback) {
+ var buf = Buffer.alloc(4);
+ buf.writeInt32LE(value, 0);
+ this._socket.write(buf, callback);
+ };
+ VirtualConnectionsCollection.prototype._onVirtualConnectionWasClosed = function (id) {
+ if (this._virtualConnections.hasOwnProperty(id)) {
+ delete this._virtualConnections[id];
+ }
+ };
+ return VirtualConnectionsCollection;
+ }());
+
+
+ /***/
+ }),
/* 9 */
-/***/ (function(module, exports) {
+/***/ (function (module, exports) {
-module.exports = require("events");
+ module.exports = require("events");
-/***/ }),
+ /***/
+ }),
/* 10 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-var __extends = (this && this.__extends) || (function () {
- var extendStatics = function (d, b) {
- extendStatics = Object.setPrototypeOf ||
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
- function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
- return extendStatics(d, b);
- }
- return function (d, b) {
- extendStatics(d, b);
- function __() { this.constructor = d; }
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
- };
-})();
-exports.__esModule = true;
-var stream_1 = __webpack_require__(11);
-/**
- * Represents a virtual connection. Multiple virtual connections may be multiplexed over a single physical socket connection.
- */
-var VirtualConnection = /** @class */ (function (_super) {
- __extends(VirtualConnection, _super);
- function VirtualConnection(_beginWriteCallback) {
- var _this = _super.call(this) || this;
- _this._beginWriteCallback = _beginWriteCallback;
- _this._flowing = false;
- _this._receivedDataQueue = [];
- return _this;
- }
- VirtualConnection.prototype._read = function () {
- this._flowing = true;
- // Keep pushing data until we run out, or the underlying framework asks us to stop.
- // When we finish, the 'flowing' state is detemined by whether more data is still being requested.
- while (this._flowing && this._receivedDataQueue.length > 0) {
- var nextChunk = this._receivedDataQueue.shift();
- this._flowing = this.push(nextChunk);
- }
- };
- VirtualConnection.prototype._write = function (chunk, encodingIfString, callback) {
- if (typeof chunk === 'string') {
- chunk = new Buffer(chunk, encodingIfString);
- }
- this._beginWriteCallback(chunk, callback);
- };
- VirtualConnection.prototype.onReceivedData = function (dataOrNullToSignalEOF) {
- if (this._flowing) {
- this._flowing = this.push(dataOrNullToSignalEOF);
- }
- else {
- this._receivedDataQueue.push(dataOrNullToSignalEOF);
- }
- };
- return VirtualConnection;
-}(stream_1.Duplex));
-exports.VirtualConnection = VirtualConnection;
+/***/ (function (module, exports, __webpack_require__) {
+ "use strict";
-/***/ }),
+ var __extends = (this && this.__extends) || (function () {
+ var extendStatics = function (d, b) {
+ extendStatics = Object.setPrototypeOf ||
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+ function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+ return extendStatics(d, b);
+ }
+ return function (d, b) {
+ extendStatics(d, b);
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+ };
+ })();
+ exports.__esModule = true;
+ var stream_1 = __webpack_require__(11);
+ /**
+ * Represents a virtual connection. Multiple virtual connections may be multiplexed over a single physical socket connection.
+ */
+ var VirtualConnection = /** @class */ (function (_super) {
+ __extends(VirtualConnection, _super);
+ function VirtualConnection(_beginWriteCallback) {
+ var _this = _super.call(this) || this;
+ _this._beginWriteCallback = _beginWriteCallback;
+ _this._flowing = false;
+ _this._receivedDataQueue = [];
+ return _this;
+ }
+ VirtualConnection.prototype._read = function () {
+ this._flowing = true;
+ // Keep pushing data until we run out, or the underlying framework asks us to stop.
+ // When we finish, the 'flowing' state is detemined by whether more data is still being requested.
+ while (this._flowing && this._receivedDataQueue.length > 0) {
+ var nextChunk = this._receivedDataQueue.shift();
+ this._flowing = this.push(nextChunk);
+ }
+ };
+ VirtualConnection.prototype._write = function (chunk, encodingIfString, callback) {
+ if (typeof chunk === 'string') {
+ chunk = Buffer.from(chunk, encodingIfString);
+ }
+ this._beginWriteCallback(chunk, callback);
+ };
+ VirtualConnection.prototype.onReceivedData = function (dataOrNullToSignalEOF) {
+ if (this._flowing) {
+ this._flowing = this.push(dataOrNullToSignalEOF);
+ }
+ else {
+ this._receivedDataQueue.push(dataOrNullToSignalEOF);
+ }
+ };
+ return VirtualConnection;
+ }(stream_1.Duplex));
+ exports.VirtualConnection = VirtualConnection;
+
+
+ /***/
+ }),
/* 11 */
-/***/ (function(module, exports) {
+/***/ (function (module, exports) {
-module.exports = require("stream");
+ module.exports = require("stream");
-/***/ })
-/******/ ])));
\ No newline at end of file
+ /***/
+ })
+/******/])));
diff --git a/src/Microsoft.AspNetCore.NodeServices.Sockets/Microsoft.AspNetCore.NodeServices.Sockets.csproj b/src/Microsoft.AspNetCore.NodeServices.Sockets/Microsoft.AspNetCore.NodeServices.Sockets.csproj
index 9dab54a9..453eb629 100644
--- a/src/Microsoft.AspNetCore.NodeServices.Sockets/Microsoft.AspNetCore.NodeServices.Sockets.csproj
+++ b/src/Microsoft.AspNetCore.NodeServices.Sockets/Microsoft.AspNetCore.NodeServices.Sockets.csproj
@@ -2,7 +2,7 @@
Socket-based RPC for Microsoft.AspNetCore.NodeServices.
- netstandard2.0
+ netcoreapp3.0
diff --git a/src/Microsoft.AspNetCore.NodeServices.Sockets/TypeScript/VirtualConnections/VirtualConnection.ts b/src/Microsoft.AspNetCore.NodeServices.Sockets/TypeScript/VirtualConnections/VirtualConnection.ts
index de71f607..76394409 100644
--- a/src/Microsoft.AspNetCore.NodeServices.Sockets/TypeScript/VirtualConnections/VirtualConnection.ts
+++ b/src/Microsoft.AspNetCore.NodeServices.Sockets/TypeScript/VirtualConnections/VirtualConnection.ts
@@ -27,7 +27,7 @@ export class VirtualConnection extends Duplex {
public _write(chunk: Buffer | string, encodingIfString: string, callback: EndWriteCallback) {
if (typeof chunk === 'string') {
- chunk = new Buffer(chunk as string, encodingIfString);
+ chunk = Buffer.from(chunk as string, encodingIfString);
}
this._beginWriteCallback(chunk as Buffer, callback);
diff --git a/src/Microsoft.AspNetCore.NodeServices.Sockets/TypeScript/VirtualConnections/VirtualConnectionServer.ts b/src/Microsoft.AspNetCore.NodeServices.Sockets/TypeScript/VirtualConnections/VirtualConnectionServer.ts
index 76b833d4..5dbf9698 100644
--- a/src/Microsoft.AspNetCore.NodeServices.Sockets/TypeScript/VirtualConnections/VirtualConnectionServer.ts
+++ b/src/Microsoft.AspNetCore.NodeServices.Sockets/TypeScript/VirtualConnections/VirtualConnectionServer.ts
@@ -113,7 +113,7 @@ class VirtualConnectionsCollection {
newVirtualConnection.on('finish', () => {
// The virtual connection was closed locally. Clean up locally, and notify the remote that we're done.
this._onVirtualConnectionWasClosed(header.connectionIdString);
- this._sendFrame(header.connectionIdBinary, new Buffer(0));
+ this._sendFrame(header.connectionIdBinary, Buffer.alloc(0));
});
this._virtualConnections[header.connectionIdString] = newVirtualConnection;
@@ -180,7 +180,7 @@ class VirtualConnectionsCollection {
* Sends a number serialized in the correct format for .NET to receive as a System.Int32
*/
private _sendInt32LE(value: number, callback?: EndWriteCallback) {
- const buf = new Buffer(4);
+ const buf = Buffer.alloc(4);
buf.writeInt32LE(value, 0);
this._socket.write(buf, callback);
}
diff --git a/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesOptions.cs b/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesOptions.cs
index 384abad0..6a72b002 100644
--- a/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesOptions.cs
+++ b/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesOptions.cs
@@ -6,7 +6,7 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
-using Microsoft.Extensions.Logging.Console;
+using Microsoft.Extensions.Logging.Abstractions;
namespace Microsoft.AspNetCore.NodeServices
{
@@ -58,8 +58,7 @@ public NodeServicesOptions(IServiceProvider serviceProvider)
var loggerFactory = serviceProvider.GetService();
NodeInstanceOutputLogger = loggerFactory != null
? loggerFactory.CreateLogger(LogCategoryName)
- : new ConsoleLogger(LogCategoryName, null, false);
-
+ : NullLogger.Instance;
// By default, we use this package's built-in out-of-process-via-HTTP hosting/transport
this.UseHttpHosting();
}
diff --git a/src/Microsoft.AspNetCore.NodeServices/Microsoft.AspNetCore.NodeServices.csproj b/src/Microsoft.AspNetCore.NodeServices/Microsoft.AspNetCore.NodeServices.csproj
index 6d64797f..742aa3fa 100644
--- a/src/Microsoft.AspNetCore.NodeServices/Microsoft.AspNetCore.NodeServices.csproj
+++ b/src/Microsoft.AspNetCore.NodeServices/Microsoft.AspNetCore.NodeServices.csproj
@@ -2,7 +2,7 @@
Invoke Node.js modules at runtime in ASP.NET Core applications.
- netstandard2.0
+ netcoreapp3.0
@@ -12,7 +12,7 @@
-
+
diff --git a/src/Microsoft.AspNetCore.SpaServices.Extensions/Microsoft.AspNetCore.SpaServices.Extensions.csproj b/src/Microsoft.AspNetCore.SpaServices.Extensions/Microsoft.AspNetCore.SpaServices.Extensions.csproj
index 4472217f..e263efb9 100644
--- a/src/Microsoft.AspNetCore.SpaServices.Extensions/Microsoft.AspNetCore.SpaServices.Extensions.csproj
+++ b/src/Microsoft.AspNetCore.SpaServices.Extensions/Microsoft.AspNetCore.SpaServices.Extensions.csproj
@@ -2,7 +2,7 @@
Helpers for building single-page applications on ASP.NET MVC Core.
- netstandard2.0
+ netcoreapp3.0
diff --git a/src/Microsoft.AspNetCore.SpaServices.Extensions/Util/LoggerFinder.cs b/src/Microsoft.AspNetCore.SpaServices.Extensions/Util/LoggerFinder.cs
index 54e57dea..d49b60c0 100644
--- a/src/Microsoft.AspNetCore.SpaServices.Extensions/Util/LoggerFinder.cs
+++ b/src/Microsoft.AspNetCore.SpaServices.Extensions/Util/LoggerFinder.cs
@@ -4,7 +4,7 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Logging.Console;
+using Microsoft.Extensions.Logging.Abstractions;
namespace Microsoft.AspNetCore.SpaServices.Util
{
@@ -14,11 +14,11 @@ public static ILogger GetOrCreateLogger(
IApplicationBuilder appBuilder,
string logCategoryName)
{
- // If the DI system gives us a logger, use it. Otherwise, set up a default one.
+ // If the DI system gives us a logger, use it. Otherwise, set up a default one
var loggerFactory = appBuilder.ApplicationServices.GetService();
var logger = loggerFactory != null
? loggerFactory.CreateLogger(logCategoryName)
- : new ConsoleLogger(logCategoryName, null, false);
+ : NullLogger.Instance;
return logger;
}
}
diff --git a/src/Microsoft.AspNetCore.SpaServices/Microsoft.AspNetCore.SpaServices.csproj b/src/Microsoft.AspNetCore.SpaServices/Microsoft.AspNetCore.SpaServices.csproj
index 15cf8129..0b0cfe2f 100644
--- a/src/Microsoft.AspNetCore.SpaServices/Microsoft.AspNetCore.SpaServices.csproj
+++ b/src/Microsoft.AspNetCore.SpaServices/Microsoft.AspNetCore.SpaServices.csproj
@@ -2,7 +2,7 @@
Helpers for building single-page applications on ASP.NET MVC Core.
- netstandard2.0
+ netcoreapp3.0
diff --git a/src/Microsoft.AspNetCore.SpaServices/npm/aspnet-webpack-react/package.json b/src/Microsoft.AspNetCore.SpaServices/npm/aspnet-webpack-react/package.json
index 19a2a1b7..0e469c78 100644
--- a/src/Microsoft.AspNetCore.SpaServices/npm/aspnet-webpack-react/package.json
+++ b/src/Microsoft.AspNetCore.SpaServices/npm/aspnet-webpack-react/package.json
@@ -1,6 +1,6 @@
{
"name": "aspnet-webpack-react",
- "version": "3.0.0",
+ "version": "4.0.0",
"description": "Helpers for using Webpack with React in ASP.NET Core projects. Works in conjunction with the Microsoft.AspNetCore.SpaServices NuGet package.",
"main": "index.js",
"scripts": {
@@ -17,12 +17,12 @@
"url": "https://github.com/aspnet/JavaScriptServices.git"
},
"devDependencies": {
- "@types/webpack": "^2.2.0",
+ "@types/webpack": "^4.4.0",
"rimraf": "^2.5.4",
"typescript": "^2.0.0",
- "webpack": "^2.2.0"
+ "webpack": "^4.16.0"
},
"peerDependencies": {
- "webpack": "^2.2.0"
+ "webpack": "^4.0.0"
}
}
diff --git a/src/Microsoft.AspNetCore.SpaServices/npm/aspnet-webpack-react/src/HotModuleReplacement.ts b/src/Microsoft.AspNetCore.SpaServices/npm/aspnet-webpack-react/src/HotModuleReplacement.ts
index ca1bad63..4f63516c 100644
--- a/src/Microsoft.AspNetCore.SpaServices/npm/aspnet-webpack-react/src/HotModuleReplacement.ts
+++ b/src/Microsoft.AspNetCore.SpaServices/npm/aspnet-webpack-react/src/HotModuleReplacement.ts
@@ -1,11 +1,9 @@
import * as webpack from 'webpack';
-const reactHotLoaderWebpackLoader = 'react-hot-loader/webpack';
-const reactHotLoaderPatch = 'react-hot-loader/patch';
const supportedTypeScriptLoaders = ['ts-loader', 'awesome-typescript-loader'];
export function addReactHotModuleReplacementConfig(webpackConfig: webpack.Configuration) {
- const moduleConfig = webpackConfig.module as webpack.NewModule;
+ const moduleConfig = webpackConfig.module as webpack.Module;
const moduleRules = moduleConfig.rules;
if (!moduleRules) {
return; // Unknown rules list format. Might be Webpack 1.x, which is not supported.
@@ -15,24 +13,18 @@ export function addReactHotModuleReplacementConfig(webpackConfig: webpack.Config
// to its array of loaders
for (let ruleIndex = 0; ruleIndex < moduleRules.length; ruleIndex++) {
// We only support NewUseRule (i.e., { use: ... }) because OldUseRule doesn't accept array values
- const rule = moduleRules[ruleIndex] as webpack.NewUseRule;
+ const rule = moduleRules[ruleIndex] as webpack.RuleSetRule;
if (!rule.use) {
continue;
}
// We're looking for the first 'use' value that's a TypeScript loader
- const loadersArray = rule.use instanceof Array ? rule.use : [rule.use];
+ const loadersArray: webpack.RuleSetUseItem[] = rule.use instanceof Array ? rule.use : [rule.use as webpack.RuleSetUseItem];
const isTypescriptLoader = supportedTypeScriptLoaders.some(typeScriptLoaderName => containsLoader(loadersArray, typeScriptLoaderName));
if (!isTypescriptLoader) {
continue;
}
- // This is the one - prefix it with the react-hot-loader loader
- // (unless it's already in there somewhere)
- if (!containsLoader(loadersArray, reactHotLoaderWebpackLoader)) {
- loadersArray.unshift(reactHotLoaderWebpackLoader);
- rule.use = loadersArray; // In case we normalised it to an array
- }
break;
}
@@ -48,19 +40,14 @@ export function addReactHotModuleReplacementConfig(webpackConfig: webpack.Config
// Normalise to array
entryConfig[entrypointName] = [entryConfig[entrypointName] as string];
}
-
- let entryValueArray = entryConfig[entrypointName] as string[];
- if (entryValueArray.indexOf(reactHotLoaderPatch) < 0) {
- entryValueArray.unshift(reactHotLoaderPatch);
- }
});
}
-function containsLoader(loadersArray: webpack.Loader[], loaderName: string) {
+function containsLoader(loadersArray: webpack.RuleSetUseItem[], loaderName: string) {
return loadersArray.some(loader => {
// Allow 'use' values to be either { loader: 'name' } or 'name'
// No need to support legacy webpack.OldLoader
- const actualLoaderName = (loader as webpack.NewLoader).loader || (loader as string);
+ const actualLoaderName = (loader as webpack.RuleSetLoader).loader || (loader as string);
return actualLoaderName && new RegExp(`\\b${ loaderName }\\b`).test(actualLoaderName);
});
}