Merge branch 'release-3.1.0' into leonardo/performance-optimizations

This commit is contained in:
Leonardo Venturini
2024-10-22 10:13:16 -04:00
22 changed files with 140 additions and 179 deletions

4
.envrc
View File

@@ -27,6 +27,10 @@ function @test-self {
@meteor self-test "$@"
}
function @test-in-console {
"$ROOT_DIR/packages/test-in-console/run.sh" "$@"
}
function @check-syntax {
node "$ROOT_DIR/scripts/admin/check-legacy-syntax/check-syntax.js"
}

View File

@@ -22,6 +22,9 @@ env:
jobs:
test:
runs-on: windows-2019-meteor
concurrency:
group: ${{ github.head_ref }}-meteor-selftest-windows
cancel-in-progress: true
steps:
- name: Checkout code

View File

@@ -0,0 +1,52 @@
name: Test Deprecated Packages
# Disabled until we figure out how to fix the error from puppeteer
# Runs on Travis CI for now
#
#on:
# push:
# branches:
# - main
# pull_request:
jobs:
build:
runs-on: ubuntu-latest
concurrency:
group: ${{ github.head_ref }}-test-deprecated-packages
cancel-in-progress: true
timeout-minutes: 60
env:
PUPPETEER_DOWNLOAD_PATH: /home/runner/.npm/chromium
steps:
- name: Update and install dependencies
run: sudo apt-get update && sudo apt-get install -y libnss3 g++-12
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: 20.15.1
- name: Cache Node.js modules
uses: actions/cache@v3
with:
path: |
~/.npm
.meteor
.babel-cache
dev_bundle
/home/runner/.npm/chromium
key: ${{ runner.os }}-node-${{ hashFiles('meteor', '**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install dependencies
run: npm install
- name: Run tests
run: ./packages/test-in-console/run.sh

View File

@@ -171,35 +171,35 @@ updateText.run.call({ userId: 'abcd' }, {
As you can see, this approach to calling Methods results in a better development workflow - you can more easily deal with the different parts of the Method separately and test your code without having to deal with Meteor internals. But this approach requires you to write a lot of boilerplate on the Method definition side.
<h3 id="validated-method">Advanced Methods with mdg:validated-method</h3>
<h3 id="jam-method">Advanced Methods with jam:method</h3>
To alleviate some of the boilerplate that's involved in correct Method definitions, we've published a wrapper package called `mdg:validated-method` that does most of this for you. Here's the same Method as above, but defined with the package:
To alleviate some of the boilerplate that's involved in correct Method definitions, you can use a package called `jam:method` that does most of this for you. Here's the same Method as above, but defined with the package:
```js
import { ValidatedMethod } from 'meteor/mdg:validated-method';
import { createMethod } from 'meteor/jam:method';
export const updateText = new ValidatedMethod({
export const updateText = createMethod({
name: 'todos.updateText',
validate: new SimpleSchema({
schema: new SimpleSchema({
todoId: { type: String },
newText: { type: String }
}).validator(),
run({ todoId, newText }) {
const todo = Todos.findOne(todoId);
}),
async run({ todoId, newText }) {
const todo = await Todos.findOneAsync(todoId);
if (!todo.editableBy(this.userId)) {
throw new Meteor.Error('todos.updateText.unauthorized',
'Cannot edit todos in a private list that is not yours');
}
Todos.update(todoId, {
Todos.updateAsync(todoId, {
$set: { text: newText }
});
}
});
```
You call it the same way you call the advanced Method above, but the Method definition is significantly simpler. We believe this style of Method lets you clearly see the important parts - the name of the Method sent over the wire, the format of the expected arguments, and the JavaScript namespace by which the Method can be referenced. Validated methods only accept a single argument and a callback function.
You call it the same way you call the advanced Method above, but the Method definition is significantly simpler. We believe this style of Method lets you clearly see the important parts - the name of the Method sent over the wire, the format of the expected arguments, and the JavaScript namespace by which the Method can be referenced.
<h2 id="errors">Error handling</h2>
@@ -227,17 +227,13 @@ When the server was not able to complete the user's desired action because of a
When a Method call fails because the arguments are of the wrong type, it's good to throw a `ValidationError`. This works like `Meteor.Error`, but is a custom constructor that enforces a standard error format that can be read by different form and validation libraries. In particular, if you are calling this Method from a form, throwing a `ValidationError` will make it possible to display nice error messages next to particular fields in the form.
When you use `mdg:validated-method` with `simpl-schema` as demonstrated above, this type of error is thrown for you.
Read more about the error format in the [`mdg:validation-error` docs](https://atmospherejs.com/mdg/validation-error).
<h3 id="handling-errors">Handling errors</h3>
When you call a Method, any errors thrown by it will be returned in the callback. At this point, you should identify which error type it is and display the appropriate message to the user. In this case, it is unlikely that the Method will throw a `ValidationError` or an internal server error, so we will only handle the unauthorized error:
```js
// Call the Method
updateText.call({
updateText({
todoId: '12345',
newText: 'This is a todo item.'
}, (err, res) => {
@@ -261,7 +257,7 @@ We'll talk about how to handle the `ValidationError` in the section on forms bel
<h3 id="throw-stub-exceptions">Errors in Method simulation</h3>
When a Method is called, it usually runs twice---once on the client to simulate the result for Optimistic UI, and again on the server to make the actual change to the database. This means that if your Method throws an error, it will likely fail on the client _and_ the server. For this reason, `ValidatedMethod` turns on undocumented option in Meteor to avoid calling the server-side implementation if the simulation throws an error.
When a Method is called, it usually runs twice---once on the client to simulate the result for Optimistic UI, and again on the server to make the actual change to the database. This means that if your Method throws an error, it will likely fail on the client _and_ the server. For this reason, `jam:method` turns on [an option](https://github.com/jamauro/method#options-for-meteorapplyasync) in Meteor to avoid calling the server-side implementation if the simulation throws an error.
While this behavior is good for saving server resources in cases where a Method will certainly fail, it's important to make sure that the simulation doesn't throw an error in cases where the server Method would have succeeded (for example, if you didn't load some data on the client that the Method needs to do the simulation properly). In this case, you can wrap server-side-only logic in a block that checks for a method simulation:
@@ -283,13 +279,13 @@ const amountRegEx = /^\d*\.(\d\d)?$/;
// This Method encodes the form validation requirements.
// By defining them in the Method, we do client and server-side
// validation in one place.
export const insert = new ValidatedMethod({
export const insert = createMethod({
name: 'Invoices.methods.insert',
validate: new SimpleSchema({
schema: new SimpleSchema({
email: { type: String, regEx: emailRegEx },
description: { type: String, min: 5 },
amount: { type: String, regEx: amountRegEx }
}).validator(),
}),
run(newInvoice) {
// In here, we can be sure that the newInvoice argument is
// validated.
@@ -299,7 +295,7 @@ export const insert = new ValidatedMethod({
'Must be logged in to create an invoice.');
}
Invoices.insert(newInvoice)
Invoices.insertAsync(newInvoice)
}
});
```
@@ -355,7 +351,7 @@ Template.Invoices_newInvoice.events({
amount: event.target.amount.value
};
insert.call(data, (err, res) => {
insert(data, (err, res) => {
if (err) {
if (err.error === 'validation-error') {
// Initialize error object
@@ -434,9 +430,9 @@ If we defined this Method in client and server code, as all Methods should be, a
The client enters a special mode where it tracks all changes made to client-side collections, so that they can be rolled back later. When this step is complete, the user of your app sees their UI update instantly with the new content of the client-side database, but the server hasn't received any data yet.
If an exception is thrown from the Method simulation, then by default Meteor ignores it and continues to step (2). If you are using `ValidatedMethod` or pass a special `throwStubExceptions` option to `Meteor.apply`, then an exception thrown from the simulation will stop the server-side Method from running at all.
If an exception is thrown from the Method simulation, then by default Meteor ignores it and continues to step (2). If you are using `jam:method` or pass a special `throwStubExceptions` [option](https://github.com/jamauro/method#options-for-meteorapplyasync) to `Meteor.apply`, then an exception thrown from the simulation will stop the server-side Method from running at all.
The return value of the Method simulation is discarded, unless the `returnStubValue` option is passed when calling the Method, in which case it is returned to the Method caller. ValidatedMethod passes this option by default.
The return value of the Method simulation is discarded, unless the `returnStubValue` option is passed when calling the Method, in which case it is returned to the Method caller. `jam:method` passes this option by default.
<h4 id="lifecycle-ddp-message">2. A `method` DDP message is sent to the server</h4>

View File

@@ -80,9 +80,9 @@ Meteor.methods({
If someone comes along and passes a non-ID selector like `{}`, they will end up deleting the entire collection.
<h3 id="validated-method">mdg:validated-method</h3>
<h3 id="jam-method">jam:method</h3>
To help you write good Methods that exhaustively validate their arguments, we've written a wrapper package for Methods that enforces argument validation. Read more about how to use it in the [Methods article](methods.html#validated-method). The rest of the code samples in this article will assume that you are using this package. If you aren't, you can still apply the same principles but the code will look a little different.
To help you write good Methods that exhaustively validate their arguments, you can use a community package for Methods that enforces argument validation. Read more about how to use it in the [Methods article](methods.html#jam-method). The rest of the code samples in this article will assume that you are using this package. If you aren't, you can still apply the same principles but the code will look a little different.
<h3 id="user-id-client">Don't pass userId from the client</h3>
@@ -200,7 +200,8 @@ if (Meteor.isServer) {
This will make every Method only callable 5 times per second per connection. This is a rate limit that shouldn't be noticeable by the user at all, but will prevent a malicious script from totally flooding the server with requests. You will need to tune the limit parameters to match your app's needs.
If you're using validated methods, there's an available [ddp-rate-limiter-mixin](https://github.com/nlhuykhang/ddp-rate-limiter-mixin).
If you're using `jam:method`, it comes with built in [rate-limiting](https://github.com/jamauro/method#rate-limiting).
<h2 id="publications">Publications</h2>

View File

@@ -2,9 +2,9 @@
"lockfileVersion": 4,
"dependencies": {
"@types/node": {
"version": "22.7.5",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz",
"integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ=="
"version": "22.7.6",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.6.tgz",
"integrity": "sha512-/d7Rnj0/ExXDMcioS78/kf1lMzYk4BZV8MZGTBKzTGZ6/406ukkbYlIsZmMPhcR5KlkunDHQLrtAVmSq7r+mSw=="
},
"@types/notp": {
"version": "2.0.5",
@@ -32,9 +32,9 @@
"integrity": "sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA=="
},
"tslib": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA=="
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz",
"integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA=="
},
"undici-types": {
"version": "6.19.8",

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Make HTTP calls to remote servers",
version: '3.0.0-beta300.7',
version: '3.0.0',
deprecated: 'Please use the fetch package'
});

View File

@@ -32,9 +32,9 @@
"integrity": "sha512-fKSWtyNQTclfi1A+s2KU91/r1mfANG1ZibxTdCwJGfV1J9UwcV22plFOm0wkaq4WzqW87zxiAkyp2Ho1Wn1NnA=="
},
"caniuse-db": {
"version": "1.0.30001640",
"resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30001640.tgz",
"integrity": "sha512-K8/5iWoH/NULlqJz/iaopQJraQCHGcFGvs8dmTpAH7GyvoQu2Xq8ht3jq2c+wNck4bgQu/PHu2GN2mJfUj9qtw=="
"version": "1.0.30001669",
"resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30001669.tgz",
"integrity": "sha512-GK+G6CnRZ7IY2J2H3bcm9kshwHcJ4ZWDC5u9WaIh7DQAAHHeuxIPtaZd15GMTmGvGbDx/u1AcQs3MYur9Tem7A=="
},
"concat-map": {
"version": "0.0.1",
@@ -47,9 +47,9 @@
"integrity": "sha512-OI38lO4JQQX2GSisTqwiSFxiWNmLajXdW4tCCxAuiwGKjusHALQadSHBSxGlU8lrFp47IkLuU2AfSYz31qpETQ=="
},
"debug": {
"version": "4.3.5",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
"integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg=="
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="
},
"fs.realpath": {
"version": "1.0.0",
@@ -97,9 +97,9 @@
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw=="
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"multi-stage-sourcemap": {
"version": "0.2.1",

View File

@@ -2,9 +2,9 @@
"lockfileVersion": 4,
"dependencies": {
"@types/node": {
"version": "22.7.5",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz",
"integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ=="
"version": "22.7.6",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.6.tgz",
"integrity": "sha512-/d7Rnj0/ExXDMcioS78/kf1lMzYk4BZV8MZGTBKzTGZ6/406ukkbYlIsZmMPhcR5KlkunDHQLrtAVmSq7r+mSw=="
},
"@types/nodemailer": {
"version": "6.4.14",

View File

@@ -53,31 +53,31 @@ var ExpectationManager = function (test, onComplete) {
};
Object.assign(ExpectationManager.prototype, {
expect: function (...args) {
expect: function (/* arguments */) {
var self = this;
if (typeof args[0] === "function")
var expected = args[0];
if (typeof arguments[0] === "function")
var expected = arguments[0];
else
var expected = args;
var expected = Array.from(arguments);
if (self.closed)
throw new Error("Too late to add more expectations to the test");
self.outstanding++;
return async function (...args) {
return async function (/* arguments */) {
if (self.dead)
return;
if (typeof expected === "function") {
try {
await expected.apply({}, args);
await expected.apply({}, arguments);
} catch (e) {
if (self.cancel())
self.test.exception(e);
}
} else {
self.test.equal(args, expected);
self.test.equal(Array.from(arguments), expected);
}
self.outstanding--;
@@ -115,12 +115,12 @@ testAsyncMulti = function (name, funcs, { isOnly = false } = {}) {
const addFunction = isOnly ? Tinytest.onlyAsync : Tinytest.addAsync;
addFunction(name, function (test, onComplete) {
var remaining = Object.assign({}, funcs);
var remaining = [...funcs]
var context = {};
var i = 0;
var runNext = function () {
var func = Object.values(remaining).shift();
var func = remaining.shift();
if (!func) {
delete test.extraDetails.asyncBlock;
onComplete();

View File

@@ -1,4 +1,3 @@
import isEmpty from 'lodash.isempty';
import isEqual from 'lodash.isequal';
// This file allows you to write tests that expect certain callbacks to be
@@ -24,11 +23,9 @@ var CallbackLogger = function (test, callbackNames) {
var self = this;
self._log = [];
self._test = test;
self._yielded = false;
callbackNames.forEach(function (callbackName) {
self[callbackName] = function () {
var args = Array.from(arguments);
self._log.push({callback: callbackName, args: args});
self[callbackName] = function (...args) {
self._log.push({ callback: callbackName, args });
};
});
};
@@ -36,7 +33,7 @@ var CallbackLogger = function (test, callbackNames) {
CallbackLogger.prototype.expectResult = async function (callbackName, args) {
var self = this;
await self._waitForLengthOrTimeout(1);
if (isEmpty(self._log)) {
if (self._log.length === 0) {
self._test.fail(["Expected callback " + callbackName + " got none"]);
return;
}
@@ -78,8 +75,10 @@ CallbackLogger.prototype.expectResultUnordered = async function (list) {
await self._waitForLengthOrTimeout(list.length);
list = [...list]; // shallow copy.
list = [...list];
var i = list.length;
while (i > 0) {
var found = false;
var dequeued = self._log.shift();
@@ -114,4 +113,4 @@ CallbackLogger.prototype.expectNoResult = async function (fn) {
await self._waitForLengthOrTimeout(0);
self._expectNoResultImpl();
};
};

View File

@@ -1,5 +1,3 @@
import isString from 'lodash.isstring';
// Establish a connection from the server to the server, and wait
// until the client side of the connection has received the session
// id. On success call `succeeded` with two arguments, the client
@@ -15,7 +13,7 @@ makeTestConnection = function (test, succeeded, failed) {
// Add incoming connections to `serverConns`.
var onConnectionHandle = Meteor.onConnection(function (serverConn) {
test.isTrue(isString(serverConn.id), "connection handle id exists and is a string");
test.isTrue(typeof serverConn.id === 'string', "connection handle id exists and is a string");
if (serverConns[serverConn.id]) {
test.fail("onConnection callback called multiple times for same session id");
failed();

View File

@@ -5,9 +5,7 @@ Package.describe({
Npm.depends({
'lodash.isequal': '4.5.0',
'lodash.isempty': '4.4.0',
'lodash.isstring': '4.0.1'
});
})
Package.onUse(function (api) {
api.use([

View File

@@ -61,7 +61,7 @@ Tinytest.add("test-helpers - try_all_permutations", function (test) {
var seen = {};
for (var i = 0; i < n; i++)
fs.push(function (x) { seq += x + "_"; }.bind(null, i));
fs.push((function (x) { seq += x + "_"; }).bind(null, i));
try_all_permutations(
function () {seq = "";},
fs,

View File

@@ -4,7 +4,7 @@ Package.describe({
});
Package.onUse(function(api) {
api.use(['tinytest', 'random', 'ejson', 'check']);
api.use(['tinytest', 'random', 'ejson', 'check', 'ecmascript']);
api.use('fetch', 'server');
api.export('TEST_STATUS', 'client');
@@ -13,9 +13,7 @@ Package.onUse(function(api) {
api.addFiles(['reporter.js'], 'server');
// This is to be run by phantomjs, not as part of normal package code.
api.addAssets('phantomRunner.js', 'server');
api.addAssets('puppeteerRunner.js', 'server');
api.addAssets('puppeteer_runner.js', 'server');
api.export('runTests');
});

View File

@@ -1,69 +0,0 @@
var createPage = require('webpage').create;
var system = require('system');
var platform = system.args[1] || 'local';
var platformUrl = system.env.URL + platform;
var testUrls = [
// Additional application URLs can be added here to re-run tests in
// PhantomJS with different query parameter-based configurations.
platformUrl
];
function runNextUrl() {
var url = testUrls.shift();
if (!url) {
phantom.exit(0);
return;
}
console.log('Running Meteor tests in PhantomJS... ' + url);
var page = createPage();
page.onConsoleMessage = function(message) {
console.log(message);
};
page.open(url);
function poll() {
if (isDone(page)) {
var failCount = getFailCount(page);
if (failCount > 0) {
phantom.exit(1);
} else {
page.close();
setTimeout(runNextUrl, 1000);
}
} else {
setTimeout(poll, 1000);
}
}
poll();
}
function isDone(page) {
return page.evaluate(function() {
if (typeof TEST_STATUS !== 'undefined') {
return TEST_STATUS.DONE;
}
return typeof DONE !== 'undefined' && DONE;
});
}
function getFailCount(page) {
return page.evaluate(function() {
if (typeof TEST_STATUS !== 'undefined') {
return TEST_STATUS.FAILURES;
}
if (typeof FAILURES === 'undefined') {
return 1;
}
return 0;
});
}
runNextUrl();

View File

@@ -5,6 +5,10 @@ let testNumber = 0;
async function runNextUrl(browser) {
const page = await browser.newPage();
// page.on('console', msg => {
// console.log('PAGE LOG:', msg.text());
// });
page.on('console', async msg => {
// this is a way to make sure the travis does not timeout
// if the test is running for too long without any output to the console (10 minutes)
@@ -58,7 +62,7 @@ async function runNextUrl(browser) {
}
}
poll();
await poll();
}
/**
@@ -130,9 +134,10 @@ async function runTests() {
'--disable-setuid-sandbox',
'--disable-web-security',
],
headless: "new",
});
console.log(`Using version: ${await browser.version()}`);
runNextUrl(browser);
await runNextUrl(browser)
}
runTests().catch((e) =>

View File

@@ -1,14 +1,7 @@
// A hacky way to extract the phantom runner script from the package.
if (process.env.WRITE_RUNNER_JS) {
Npm.require('fs').writeFileSync(
process.env.WRITE_RUNNER_JS, Buffer.from(Assets.getBinary('runner.js')));
}
let url = null;
var url = null;
if (Meteor.settings &&
Meteor.settings.public &&
Meteor.settings.public.runId &&
Meteor.settings.public.reportTo) {
if (Meteor.settings?.public?.runId &&
Meteor.settings?.public?.reportTo) {
url = Meteor.settings.public.reportTo +
"/report/" +
Meteor.settings.public.runId;

View File

@@ -8,36 +8,21 @@
cd $(dirname $0)/../..
export METEOR_HOME=`pwd`
export phantom=$phantom
# only install dependencies if required
if [ "$phantom" = true ]
then
# Just in case these packages haven't been installed elsewhere.
./meteor npm install -g phantomjs-prebuilt browserstack-webdriver
else
# Installs into dev_bundle/lib/node_modules/puppeteer.
./meteor npm install -g puppeteer@20.4.0
fi
# Installs into dev_bundle/lib/node_modules/puppeteer.
./meteor npm install -g puppeteer@20.4.0
export PATH=$METEOR_HOME:$PATH
# synchronously get the dev bundle and NPM modules if they're not there.
./meteor --help || exit 1
export URL='http://127.0.0.1:4096/'
export METEOR_PACKAGE_DIRS='packages/deprecated'
exec 3< <(meteor test-packages --driver-package test-in-console -p 4096 --exclude ${TEST_PACKAGES_EXCLUDE:-''} $1)
exec 3< <(./meteor test-packages --driver-package test-in-console -p 4096 --exclude ${TEST_PACKAGES_EXCLUDE:-''} $1)
EXEC_PID=$!
trap "pkill -TERM -P $EXEC_PID; exit 1" SIGINT
sed '/test-in-console listening$/q' <&3
if [ "$phantom" = true ]
then
./dev_bundle/bin/phantomjs "$METEOR_HOME/packages/test-in-console/phantomRunner.js"
else
node "$METEOR_HOME/packages/test-in-console/puppeteerRunner.js"
fi
node --trace-warnings "$METEOR_HOME/packages/test-in-console/puppeteer_runner.js"
STATUS=$?

View File

@@ -13,7 +13,6 @@ Npm.depends({
send: "1.1.0",
"stream-to-string": "1.2.1",
qs: "6.13.0",
'lodash.has': '4.5.2',
"useragent-ng": "2.4.3",
"tmp": "0.2.3",
});

View File

@@ -19,7 +19,6 @@ import {
} from './socket_file.js';
import cluster from 'cluster';
import { execSync } from 'child_process';
import has from 'lodash.has';
var SHORT_SOCKET_TIMEOUT = 5 * 1000;
var LONG_SOCKET_TIMEOUT = 120 * 1000;
@@ -622,7 +621,7 @@ WebAppInternals.staticFilesMiddleware = async function(
};
if (
has(additionalStaticJs, pathname) &&
pathname in additionalStaticJs &&
!WebAppInternals.inlineScriptsAllowed()
) {
serveStaticJs(additionalStaticJs[pathname]);

View File

@@ -202,7 +202,7 @@ exports.sleepMs = function (ms) {
// Return a short, high entropy string without too many funny
// characters in it.
exports.randomToken = function () {
return (Math.random() * 0x100000000 + 1).toString(36);
return (Math.random() * 0x100000000 + 1).toString(36).replace('.', '');
};
// Like utils.randomToken, except a legal variable name, i.e. the first