Merge branch 'release-2.5' into feature/passwordless-ui

This commit is contained in:
Jan Dvorak
2021-10-14 10:56:00 +02:00
29 changed files with 2420 additions and 733 deletions

View File

@@ -8,7 +8,6 @@ cache:
- ".meteor"
- ".babel-cache"
script:
- export TEST_PACKAGES_EXCLUDE="less"
- export phantom=false
# to skip Downloading Chromium on every run
# https://github.com/dfernandez79/puppeteer/blob/main/README.md#q-chromium-gets-downloaded-on-every-npm-ci-run-how-can-i-cache-the-download

View File

@@ -54,6 +54,7 @@
- Update `cordova-plugin-meteor-webapp` to v2
- Removed dependency on `cordova-plugin-whitelist` as it is now included in core
- Cordova Meteor plugin is now using AndroidX
- Added new settings option `Meteor.settings.packages.webapp.alwaysReturnContent` that will always return content on requests like `POST`, essentially enabling behavior prior to Meteor 2.3.1.
#### Independent Releases
@@ -75,6 +76,16 @@
* `ecmascript-runtime-client@0.12.1`
- Revert `core-js` to v3.15.2 due to issues in legacy build with arrays, [see issue for more details](https://github.com/meteor/meteor/issues/11662)
* `modern-browsers@0.1.7`
- Added `firefoxMobile` as an alias for `firefox`
## v2.4.1, 2021-10-12
#### Meteor Version Release
* `meteor-tool@2.4.1`
- Patch to make 2.4.1 compatible with Push to Deploy feature in Galaxy (Meteor Cloud)
## v2.4, 2021-09-15
#### Highlights
@@ -187,6 +198,13 @@
* `callback-hook@1.4.0`
- Added `forEach` iterator to be more in-line with the ES use for iterations. `each` is now deprecated, but will remain supported.
## v2.3.7, 2021-10-12
#### Meteor Version Release
* `meteor-tool@2.3.7`
- Patch to make 2.3.7 compatible with Push to Deploy feature in Galaxy (Meteor Cloud)
## v2.3.6, 2021-09-02
@@ -541,6 +559,13 @@
* `react-fast-refresh@0.1.1`
- Fixed the package to work in IE11
## v2.2.4, 2021-10-12
#### Meteor Version Release
* `meteor-tool@2.2.4`
- Patch to make 2.2.4 compatible with Push to Deploy feature in Galaxy (Meteor Cloud)
## v2.2.3, 2021-08-12
@@ -643,6 +668,14 @@
* `webapp@1.10.1`
- Fix for UNIX sockets with node cluster. [#11369](https://github.com/meteor/meteor/pull/11369)
## v2.1.2, 2021-10-12
#### Meteor Version Release
* `meteor-tool@2.1.2`
- Patch to make 2.1.2 compatible with Push to Deploy feature in Galaxy (Meteor Cloud)
## v2.1.1, 2021-04-06
### Changes
@@ -687,6 +720,13 @@
* N/A
## v2.0.1, 2021-10-12
#### Meteor Version Release
* `meteor-tool@2.0.1`
- Patch to make 2.0.1 compatible with Push to Deploy feature in Galaxy (Meteor Cloud)
## v2.0, 2021-01-20
### Changes
@@ -753,6 +793,13 @@ Simple run `meteor update` in your app.
Great new features and no breaking changes (except one package deprecation). You can always check our [Roadmap](./Roadmap.md) to understand what is next.
## v1.12.2, 2021-10-12
#### Meteor Version Release
* `meteor-tool@1.12.2`
- Patch to make 1.12.2 compatible with Push to Deploy feature in Galaxy (Meteor Cloud)
## v1.12.1, 2021-01-06
### Breaking changes

View File

@@ -249,7 +249,7 @@ Here is a list of the Babel transformers that are currently enabled:
The ECMAScript 2015 standard library has grown to include new APIs and
data structures, some of which can be implemented ("polyfilled") using
JavaScript that runs in all engines and browsers today. Here are three new
JavaScript that runs in all engines and browsers today. Here are four new
constructors that are guaranteed to be available when the `ecmascript`
package is installed:

View File

@@ -40,4 +40,5 @@ Package.onTest(function(api) {
api.addFiles('bare-test-file.js', ['client', 'server'], {
bare: true,
});
api.addFiles('runtime-tests-client.js', ['client', 'web.browser.legacy']);
});

View File

@@ -0,0 +1,22 @@
// Regression test for web.browser.legacy - see https://github.com/meteor/meteor/issues/11662
Tinytest.add('ecmascript - runtime - NodeList spread', test => {
const div = document.createElement('div');
document.body.appendChild(div);
for (let i = 0; i < 5; i++) {
const child = document.createElement('div');
child.innerText = `child ${i}`;
div.appendChild(child);
}
try {
test.equal(div.childNodes?.length, 5);
const arr = [...div.childNodes];
arr.forEach((el, i) => {
test.equal(el.innerText, `child ${i}`);
});
} finally {
document.body.removeChild(div);
}
});

View File

@@ -1,28 +1,28 @@
const isNode8OrLater = Meteor.isServer &&
parseInt(process.versions.node) >= 8;
const isNode8OrLater = Meteor.isServer && parseInt(process.versions.node) >= 8;
Tinytest.add("ecmascript - runtime - template literals", (test) => {
Tinytest.add('ecmascript - runtime - template literals', test => {
function dump(strings, ...expressions) {
const copy = Object.create(null);
Object.assign(copy, strings);
copy.raw = strings.raw;
return [copy, expressions];
};
}
const foo = "B";
const foo = 'B';
test.equal(`\u0041${foo}C`, "ABC");
test.equal(`\u0041${foo}C`, 'ABC');
test.equal(dump`\u0041${foo}C`, [{
0: "A",
1: "C",
raw: ["\\u0041", "C"]
}, [
"B"
]]);
test.equal(dump`\u0041${foo}C`, [
{
0: 'A',
1: 'C',
raw: ['\\u0041', 'C'],
},
['B'],
]);
});
Tinytest.add("ecmascript - runtime - classes - basic", (test) => {
Tinytest.add('ecmascript - runtime - classes - basic', test => {
{
class Foo {
constructor(x) {
@@ -35,7 +35,7 @@ Tinytest.add("ecmascript - runtime - classes - basic", (test) => {
// Foo(); // called without `new`
// });
test.equal((new Foo(3)).x, 3);
test.equal(new Foo(3).x, 3);
}
{
@@ -51,9 +51,9 @@ Tinytest.add("ecmascript - runtime - classes - basic", (test) => {
// Foo(); // called without `new`
// });
test.equal((new Foo(3)).x, 3);
test.isTrue((new Foo(3)) instanceof Foo);
test.isTrue((new Foo(3)) instanceof Bar);
test.equal(new Foo(3).x, 3);
test.isTrue(new Foo(3) instanceof Foo);
test.isTrue(new Foo(3) instanceof Bar);
}
{
@@ -68,11 +68,11 @@ Tinytest.add("ecmascript - runtime - classes - basic", (test) => {
}
test.equal(Foo.staticMethod(), 'classy');
test.equal((new Foo).prototypeMethod(), 'prototypical');
test.equal(new Foo().prototypeMethod(), 'prototypical');
}
});
Tinytest.add("ecmascript - runtime - classes - use before declare", (test) => {
Tinytest.add('ecmascript - runtime - classes - use before declare', test => {
const x = function asdf() {};
if (typeof asdf === 'function') {
// We seem to be in IE 8, where function names leak into the enclosing
@@ -88,9 +88,7 @@ Tinytest.add("ecmascript - runtime - classes - use before declare", (test) => {
});
});
Tinytest.add("ecmascript - runtime - classes - inheritance", (test) => {
Tinytest.add('ecmascript - runtime - classes - inheritance', test => {
// uses `babelHelpers.inherits`
{
class Foo {
@@ -98,7 +96,7 @@ Tinytest.add("ecmascript - runtime - classes - inheritance", (test) => {
return 1;
}
}
Foo.static2 = function () {
Foo.static2 = function() {
return 2;
};
@@ -128,12 +126,14 @@ Tinytest.add("ecmascript - runtime - classes - inheritance", (test) => {
}
});
Tinytest.add("ecmascript - runtime - classes - computed props", (test) => {
Tinytest.add('ecmascript - runtime - classes - computed props', test => {
{
const frob = "inc";
const frob = 'inc';
class Foo {
static [frob](n) { return n+1; }
static [frob](n) {
return n + 1;
}
}
test.equal(Foo.inc(3), 4);
@@ -145,35 +145,39 @@ if (Meteor.isServer) {
// in classes on browsers that support them in the first place, and on
// the server. (Technically they just need a working
// Object.defineProperty, found in IE9+ and all modern environments.)
Tinytest.add("ecmascript - runtime - classes - getters/setters", (test) => {
Tinytest.add('ecmascript - runtime - classes - getters/setters', test => {
// uses `babelHelpers.createClass`
class Foo {
get two() { return 1+1; }
static get three() { return 1+1+1; }
get two() {
return 1 + 1;
}
static get three() {
return 1 + 1 + 1;
}
}
test.equal((new Foo).two, 2);
test.equal(new Foo().two, 2);
test.equal(Foo.three, 3);
});
}
export const testExport = "oyez";
export const testExport = 'oyez';
Tinytest.add("ecmascript - runtime - classes - properties", (test) => {
Tinytest.add('ecmascript - runtime - classes - properties', test => {
class ClassWithProperties {
property = ["prop", "rty"].join("e");
property = ['prop', 'rty'].join('e');
static staticProp = 1234;
check = (self) => {
import { testExport as oyez } from "./runtime-tests.js";
test.equal(oyez, "oyez");
check = self => {
import { testExport as oyez } from './runtime-tests.js';
test.equal(oyez, 'oyez');
test.isTrue(self === this);
test.equal(this.property, "property");
test.equal(this.property, 'property');
};
method() {
import { testExport as oyez } from "./runtime-tests.js";
test.equal(oyez, "oyez");
import { testExport as oyez } from './runtime-tests.js';
test.equal(oyez, 'oyez');
}
}
@@ -189,16 +193,16 @@ Tinytest.add("ecmascript - runtime - classes - properties", (test) => {
cwp.method();
});
Tinytest.add("ecmascript - runtime - block scope", (test) => {
Tinytest.add('ecmascript - runtime - block scope', test => {
{
const buf = [];
const thunks = [];
function print(x) {
buf.push(x);
};
}
function doLater(f) {
thunks.push(f);
};
}
for (let i = 0; i < 3; i++) {
print(i);
@@ -217,11 +221,15 @@ Tinytest.add("ecmascript - runtime - block scope", (test) => {
}
});
Tinytest.add("ecmascript - runtime - classes - super", (test) => {
Tinytest.add('ecmascript - runtime - classes - super', test => {
{
class Class1 {
foo() { return 123; }
static bar() { return 1; }
foo() {
return 123;
}
static bar() {
return 1;
}
}
class Class2 extends Class1 {}
class Class3 extends Class2 {
@@ -230,34 +238,41 @@ Tinytest.add("ecmascript - runtime - classes - super", (test) => {
}
}
test.equal((new Class3).foo(), 124);
test.equal(new Class3().foo(), 124);
}
{
class Foo {
constructor(value) { this.value = value; }
x() { return this.value; }
constructor(value) {
this.value = value;
}
x() {
return this.value;
}
}
class Bar extends Foo {
constructor() { super(123); }
x() { return super.x(); }
constructor() {
super(123);
}
x() {
return super.x();
}
}
test.equal((new Bar).x(), 123);
test.equal(new Bar().x(), 123);
}
});
Tinytest.add("ecmascript - runtime - object rest/spread", (test) => {
const middle = {b:2, c:3};
Tinytest.add('ecmascript - runtime - object rest/spread', test => {
const middle = { b: 2, c: 3 };
// uses `babelHelpers._extends`
const full = {a:1, ...middle, d:4};
test.equal(full, {a:1, b:2, c:3, d:4});
const full = { a: 1, ...middle, d: 4 };
test.equal(full, { a: 1, b: 2, c: 3, d: 4 });
});
Tinytest.add("ecmascript - runtime - spread args to new", (test) => {
const Foo = function (one, two, three) {
Tinytest.add('ecmascript - runtime - spread args to new', test => {
const Foo = function(one, two, three) {
test.isTrue(this instanceof Foo);
test.equal(one, 1);
test.equal(two, 2);
@@ -272,35 +287,38 @@ Tinytest.add("ecmascript - runtime - spread args to new", (test) => {
test.isTrue(foo.created);
});
Tinytest.add("ecmascript - runtime - Map spread", (test) => {
const map = new Map;
Tinytest.add('ecmascript - runtime - Map spread', test => {
const map = new Map();
map.set(0, 1);
map.set(1, 2);
map.set(2, 3);
test.equal([...map], [
[0, 1],
[1, 2],
[2, 3]
]);
test.equal(
[...map],
[
[0, 1],
[1, 2],
[2, 3],
]
);
});
Tinytest.add("ecmascript - runtime - Set spread", (test) => {
const set = new Set;
Tinytest.add('ecmascript - runtime - Set spread', test => {
const set = new Set();
set.add("a");
set.add('a');
set.add(1);
set.add(false);
test.equal([...set], ["a", 1, false]);
test.equal([...set], ['a', 1, false]);
});
Tinytest.add("ecmascript - runtime - destructuring", (test) => {
const obj = {a:1, b:2};
const {a, ...rest} = obj;
Tinytest.add('ecmascript - runtime - destructuring', test => {
const obj = { a: 1, b: 2 };
const { a, ...rest } = obj;
test.equal(a, 1);
test.equal(rest, {b:2});
test.equal(rest, { b: 2 });
const {} = {};
@@ -308,33 +326,33 @@ Tinytest.add("ecmascript - runtime - destructuring", (test) => {
const {} = null;
});
const [x, y, z] = function*() {
const [x, y, z] = (function*() {
let n = 1;
while (true) {
yield n++;
}
}();
})();
test.equal(x, 1);
test.equal(y, 2);
test.equal(z, 3);
});
Tinytest.addAsync("ecmascript - runtime - misc support", (test, done) => {
Tinytest.addAsync('ecmascript - runtime - misc support', (test, done) => {
// Verify that the runtime was installed.
if (Meteor.isLegacy) {
test.equal(typeof meteorBabelHelpers, "object");
test.equal(typeof meteorBabelHelpers.sanitizeForInObject, "function");
test.equal(typeof meteorBabelHelpers, 'object');
test.equal(typeof meteorBabelHelpers.sanitizeForInObject, 'function');
}
class Base {
constructor(...args) {
this.sum = 0;
args.forEach(arg => this.sum += arg);
args.forEach(arg => (this.sum += arg));
}
static inherited() {
return "inherited";
return 'inherited';
}
}
@@ -345,32 +363,35 @@ Tinytest.addAsync("ecmascript - runtime - misc support", (test, done) => {
}
// Check that static methods are inherited.
test.equal(Derived.inherited(), "inherited");
test.equal(Derived.inherited(), 'inherited');
const d = new Derived();
test.equal(d.sum, 6);
const expectedError = new Error("expected");
const expectedError = new Error('expected');
Promise.resolve("working").then(result => {
test.equal(result, "working");
throw expectedError;
}).catch(error => {
test.equal(error, expectedError);
if (Meteor.isServer) {
const Fiber = Npm.require("fibers");
// Make sure the Promise polyfill runs callbacks in a Fiber.
test.instanceOf(Fiber.current, Fiber);
}
}).then(done, error => test.exception(error));
Promise.resolve('working')
.then(result => {
test.equal(result, 'working');
throw expectedError;
})
.catch(error => {
test.equal(error, expectedError);
if (Meteor.isServer) {
const Fiber = Npm.require('fibers');
// Make sure the Promise polyfill runs callbacks in a Fiber.
test.instanceOf(Fiber.current, Fiber);
}
})
.then(done, error => test.exception(error));
});
Tinytest.addAsync("ecmascript - runtime - async fibers", (test, done) => {
if (! Meteor.isServer) {
Tinytest.addAsync('ecmascript - runtime - async fibers', (test, done) => {
if (!Meteor.isServer) {
return done();
}
const Fiber = Npm.require("fibers");
const Fiber = Npm.require('fibers');
function wait() {
return new Promise(resolve => setTimeout(resolve, 10));

View File

@@ -6,9 +6,9 @@ const hasOwn = Object.prototype.hasOwnProperty;
const browserAliases = {
chrome: [
// chromeMobile*, per https://github.com/meteor/meteor/pull/9793,
"chromeMobile",
"chromeMobileIOS",
"chromeMobileWebView",
'chromeMobile',
'chromeMobileIOS',
'chromeMobileWebView',
// The major version number of Chromium and Headless Chrome track with the
// releases of Chrome Dev, Canary and Stable, so we should be okay to
@@ -18,19 +18,21 @@ const browserAliases = {
// Chromium is particularly important to list here since, unlike macOS
// builds, Linux builds list Chromium in the userAgent along with Chrome:
// e.g. Chromium/70.0.3538.77 Chrome/70.0.3538.77
"chromium",
"headlesschrome",
'chromium',
'headlesschrome',
],
// If a call to setMinimumBrowserVersions specifies Edge 12 as a minimum
// version, that means no version of Internet Explorer pre-Edge should
// be classified as modern. This edge:["ie"] alias effectively enforces
// that logic, because there is no IE12. #9818 #9839
edge: ["ie"],
edge: ['ie'],
firefox: ['firefoxMobile'],
// The webapp package converts browser names to camel case, so
// mobile_safari and mobileSafari should be synonymous.
mobile_safari: ["mobileSafari", "mobileSafariUI", "mobileSafariUI/WKWebView"],
mobile_safari: ['mobileSafari', 'mobileSafariUI', 'mobileSafariUI/WKWebView'],
};
// Expand the given minimum versions by reusing chrome versions for
@@ -49,7 +51,7 @@ function applyAliases(versions) {
if (hasOwn.call(lowerCaseVersions, original)) {
aliases.forEach(alias => {
alias = alias.toLowerCase();
if (! hasOwn.call(lowerCaseVersions, alias)) {
if (!hasOwn.call(lowerCaseVersions, alias)) {
lowerCaseVersions[alias] = lowerCaseVersions[original];
}
});
@@ -66,17 +68,17 @@ function applyAliases(versions) {
// webapp via request.browser, return true if that browser qualifies as
// "modern" according to all requested version constraints.
function isModern(browser) {
const lowerCaseName = browser &&
typeof browser.name === "string" &&
browser.name.toLowerCase();
const lowerCaseName =
browser && typeof browser.name === 'string' && browser.name.toLowerCase();
return !!lowerCaseName &&
return (
!!lowerCaseName &&
hasOwn.call(minimumVersions, lowerCaseName) &&
greaterThanOrEqualTo([
~~browser.major,
~~browser.minor,
~~browser.patch,
], minimumVersions[lowerCaseName].version);
greaterThanOrEqualTo(
[~~browser.major, ~~browser.minor, ~~browser.patch],
minimumVersions[lowerCaseName].version
)
);
}
// Any package that depends on the modern-browsers package can call this
@@ -90,22 +92,24 @@ function setMinimumBrowserVersions(versions, source) {
Object.keys(lowerCaseVersions).forEach(lowerCaseName => {
const version = lowerCaseVersions[lowerCaseName];
if (hasOwn.call(minimumVersions, lowerCaseName) &&
! greaterThan(version, minimumVersions[lowerCaseName].version)) {
if (
hasOwn.call(minimumVersions, lowerCaseName) &&
!greaterThan(version, minimumVersions[lowerCaseName].version)
) {
return;
}
minimumVersions[lowerCaseName] = {
version: copy(version),
source: source || getCaller("setMinimumBrowserVersions")
source: source || getCaller('setMinimumBrowserVersions'),
};
});
}
function getCaller(calleeName) {
const error = new Error;
const error = new Error();
Error.captureStackTrace(error);
const lines = error.stack.split("\n");
const lines = error.stack.split('\n');
let caller;
lines.some((line, i) => {
if (line.indexOf(calleeName) >= 0) {
@@ -120,17 +124,17 @@ Object.assign(exports, {
isModern,
setMinimumBrowserVersions,
calculateHashOfMinimumVersions() {
const { createHash } = require("crypto");
return createHash("sha1").update(
JSON.stringify(minimumVersions)
).digest("hex");
}
const { createHash } = require('crypto');
return createHash('sha1')
.update(JSON.stringify(minimumVersions))
.digest('hex');
},
});
// For making defensive copies of [major, minor, ...] version arrays, so
// they don't change unexpectedly.
function copy(version) {
if (typeof version === "number") {
if (typeof version === 'number') {
return version;
}
@@ -142,17 +146,17 @@ function copy(version) {
}
function greaterThanOrEqualTo(a, b) {
return ! greaterThan(b, a);
return !greaterThan(b, a);
}
function greaterThan(a, b) {
const as = (typeof a === "number") ? [a] : a;
const bs = (typeof b === "number") ? [b] : b;
const as = typeof a === 'number' ? [a] : a;
const bs = typeof b === 'number' ? [b] : b;
const maxLen = Math.max(as.length, bs.length);
for (let i = 0; i < maxLen; ++i) {
a = (i < as.length) ? as[i] : 0;
b = (i < bs.length) ? bs[i] : 0;
a = i < as.length ? as[i] : 0;
b = i < bs.length ? bs[i] : 0;
if (a > b) {
return true;
@@ -167,49 +171,61 @@ function greaterThan(a, b) {
}
function makeSource(feature) {
return module.id + " (" + feature + ")";
return module.id + ' (' + feature + ')';
}
setMinimumBrowserVersions({
chrome: 49,
edge: 12,
firefox: 45,
mobileSafari: [9, 2],
opera: 36,
safari: 9,
// Electron 1.0.0+ matches Chromium 49, per
// https://github.com/Kilian/electron-to-chromium/blob/master/full-versions.js
electron: 1,
}, makeSource("classes"));
setMinimumBrowserVersions(
{
chrome: 49,
edge: 12,
firefox: 45,
mobileSafari: [9, 2],
opera: 36,
safari: 9,
// Electron 1.0.0+ matches Chromium 49, per
// https://github.com/Kilian/electron-to-chromium/blob/master/full-versions.js
electron: 1,
},
makeSource('classes')
);
setMinimumBrowserVersions({
chrome: 39,
edge: 13,
firefox: 26,
mobileSafari: 10,
opera: 26,
safari: 10,
// Disallow any version of PhantomJS.
phantomjs: Infinity,
electron: [0, 20],
}, makeSource("generator functions"));
setMinimumBrowserVersions(
{
chrome: 39,
edge: 13,
firefox: 26,
mobileSafari: 10,
opera: 26,
safari: 10,
// Disallow any version of PhantomJS.
phantomjs: Infinity,
electron: [0, 20],
},
makeSource('generator functions')
);
setMinimumBrowserVersions({
chrome: 41,
edge: 13,
firefox: 34,
mobileSafari: [9, 2],
opera: 29,
safari: [9, 1],
electron: [0, 24],
}, makeSource("template literals"));
setMinimumBrowserVersions(
{
chrome: 41,
edge: 13,
firefox: 34,
mobileSafari: [9, 2],
opera: 29,
safari: [9, 1],
electron: [0, 24],
},
makeSource('template literals')
);
setMinimumBrowserVersions({
chrome: 38,
edge: 12,
firefox: 36,
mobileSafari: 9,
opera: 25,
safari: 9,
electron: [0, 20],
}, makeSource("symbols"));
setMinimumBrowserVersions(
{
chrome: 38,
edge: 12,
firefox: 36,
mobileSafari: 9,
opera: 25,
safari: 9,
electron: [0, 20],
},
makeSource('symbols')
);

View File

@@ -1,19 +1,20 @@
Package.describe({
name: "modern-browsers",
version: "0.1.6",
summary: "API for defining the boundary between modern and legacy " +
"JavaScript clients",
documentation: "README.md"
name: 'modern-browsers',
version: '0.1.7',
summary:
'API for defining the boundary between modern and legacy ' +
'JavaScript clients',
documentation: 'README.md',
});
Package.onUse(function(api) {
api.use("modules");
api.mainModule("modern.js", "server");
api.use('modules');
api.mainModule('modern.js', 'server');
});
Package.onTest(function(api) {
api.use("ecmascript");
api.use("tinytest");
api.use("modern-browsers");
api.mainModule("modern-tests.js", "server");
api.use('ecmascript');
api.use('tinytest');
api.use('modern-browsers');
api.mainModule('modern-tests.js', 'server');
});

View File

@@ -25,16 +25,19 @@ The default id generation technique is `'STRING'`.
* @param {Boolean} options.defineMutationMethods Set to `false` to skip setting up the mutation methods that enable insert/update/remove from client code. Default `true`.
*/
Mongo.Collection = function Collection(name, options) {
if (!name && (name !== null)) {
Meteor._debug("Warning: creating anonymous collection. It will not be " +
"saved or synchronized over the network. (Pass null for " +
"the collection name to turn off this warning.)");
if (!name && name !== null) {
Meteor._debug(
'Warning: creating anonymous collection. It will not be ' +
'saved or synchronized over the network. (Pass null for ' +
'the collection name to turn off this warning.)'
);
name = null;
}
if (name !== null && typeof name !== "string") {
if (name !== null && typeof name !== 'string') {
throw new Error(
"First argument to new Mongo.Collection must be a string or null");
'First argument to new Mongo.Collection must be a string or null'
);
}
if (options && options.methods) {
@@ -42,7 +45,7 @@ Mongo.Collection = function Collection(name, options) {
// "connection" directly instead of in options. (Connections must have a "methods"
// method.)
// XXX remove before 1.0
options = {connection: options};
options = { connection: options };
}
// Backwards compatibility: "connection" used to be called "manager".
if (options && options.manager && !options.connection) {
@@ -55,49 +58,52 @@ Mongo.Collection = function Collection(name, options) {
transform: null,
_driver: undefined,
_preventAutopublish: false,
...options,
...options,
};
switch (options.idGeneration) {
case 'MONGO':
this._makeNewID = function () {
var src = name ? DDP.randomStream('/collection/' + name) : Random.insecure;
return new Mongo.ObjectID(src.hexString(24));
};
break;
case 'STRING':
default:
this._makeNewID = function () {
var src = name ? DDP.randomStream('/collection/' + name) : Random.insecure;
return src.id();
};
break;
case 'MONGO':
this._makeNewID = function() {
var src = name
? DDP.randomStream('/collection/' + name)
: Random.insecure;
return new Mongo.ObjectID(src.hexString(24));
};
break;
case 'STRING':
default:
this._makeNewID = function() {
var src = name
? DDP.randomStream('/collection/' + name)
: Random.insecure;
return src.id();
};
break;
}
this._transform = LocalCollection.wrapTransform(options.transform);
if (! name || options.connection === null)
if (!name || options.connection === null)
// note: nameless collections never have a connection
this._connection = null;
else if (options.connection)
this._connection = options.connection;
else if (Meteor.isClient)
this._connection = Meteor.connection;
else
this._connection = Meteor.server;
else if (options.connection) this._connection = options.connection;
else if (Meteor.isClient) this._connection = Meteor.connection;
else this._connection = Meteor.server;
if (!options._driver) {
// XXX This check assumes that webapp is loaded so that Meteor.server !==
// null. We should fully support the case of "want to use a Mongo-backed
// collection from Node code without webapp", but we don't yet.
// #MeteorServerNull
if (name && this._connection === Meteor.server &&
typeof MongoInternals !== "undefined" &&
MongoInternals.defaultRemoteCollectionDriver) {
if (
name &&
this._connection === Meteor.server &&
typeof MongoInternals !== 'undefined' &&
MongoInternals.defaultRemoteCollectionDriver
) {
options._driver = MongoInternals.defaultRemoteCollectionDriver();
} else {
const { LocalCollectionDriver } =
require("./local_collection_driver.js");
const { LocalCollectionDriver } = require('./local_collection_driver.js');
options._driver = LocalCollectionDriver;
}
}
@@ -114,21 +120,25 @@ Mongo.Collection = function Collection(name, options) {
if (options.defineMutationMethods !== false) {
try {
this._defineMutationMethods({
useExisting: options._suppressSameNameError === true
useExisting: options._suppressSameNameError === true,
});
} catch (error) {
// Throw a more understandable error on the server for same collection name
if (error.message === `A method named '/${name}/insert' is already defined`)
if (
error.message === `A method named '/${name}/insert' is already defined`
)
throw new Error(`There is already a collection named "${name}"`);
throw error;
}
}
// autopublish
if (Package.autopublish &&
! options._preventAutopublish &&
this._connection &&
this._connection.publish) {
if (
Package.autopublish &&
!options._preventAutopublish &&
this._connection &&
this._connection.publish
) {
this._connection.publish(null, () => this.find(), {
is_auto: true,
});
@@ -136,12 +146,9 @@ Mongo.Collection = function Collection(name, options) {
};
Object.assign(Mongo.Collection.prototype, {
_maybeSetUpReplication(name, {
_suppressSameNameError = false
}) {
_maybeSetUpReplication(name, { _suppressSameNameError = false }) {
const self = this;
if (! (self._connection &&
self._connection.registerStore)) {
if (!(self._connection && self._connection.registerStore)) {
return;
}
@@ -165,11 +172,9 @@ Object.assign(Mongo.Collection.prototype, {
// stage), and so that a re-sorting of a query can take advantage of the
// full _diffQuery moved calculation instead of applying change one at a
// time.
if (batchSize > 1 || reset)
self._collection.pauseObservers();
if (batchSize > 1 || reset) self._collection.pauseObservers();
if (reset)
self._collection.remove({});
if (reset) self._collection.remove({});
},
// Apply an update.
@@ -211,8 +216,7 @@ Object.assign(Mongo.Collection.prototype, {
if (msg.msg === 'replace') {
var replace = msg.replace;
if (!replace) {
if (doc)
self._collection.remove(mongoId);
if (doc) self._collection.remove(mongoId);
} else if (!doc) {
self._collection.insert(replace);
} else {
@@ -222,16 +226,19 @@ Object.assign(Mongo.Collection.prototype, {
return;
} else if (msg.msg === 'added') {
if (doc) {
throw new Error("Expected not to find a document already present for an add");
throw new Error(
'Expected not to find a document already present for an add'
);
}
self._collection.insert({ _id: mongoId, ...msg.fields });
} else if (msg.msg === 'removed') {
if (!doc)
throw new Error("Expected to find a document already present for removed");
throw new Error(
'Expected to find a document already present for removed'
);
self._collection.remove(mongoId);
} else if (msg.msg === 'changed') {
if (!doc)
throw new Error("Expected to find a document to change");
if (!doc) throw new Error('Expected to find a document to change');
const keys = Object.keys(msg.fields);
if (keys.length > 0) {
var modifier = {};
@@ -240,7 +247,7 @@ Object.assign(Mongo.Collection.prototype, {
if (EJSON.equals(doc[key], value)) {
return;
}
if (typeof value === "undefined") {
if (typeof value === 'undefined') {
if (!modifier.$unset) {
modifier.$unset = {};
}
@@ -283,10 +290,10 @@ Object.assign(Mongo.Collection.prototype, {
// To be able to get back to the collection from the store.
_getCollection() {
return self;
}
},
});
if (! ok) {
if (!ok) {
const message = `There is already a collection named "${name}"`;
if (_suppressSameNameError === true) {
// XXX In theory we do not have to throw when `ok` is falsy. The
@@ -308,10 +315,8 @@ Object.assign(Mongo.Collection.prototype, {
///
_getFindSelector(args) {
if (args.length == 0)
return {};
else
return args[0];
if (args.length == 0) return {};
else return args[0];
},
_getFindOptions(args) {
@@ -319,12 +324,19 @@ Object.assign(Mongo.Collection.prototype, {
if (args.length < 2) {
return { transform: self._transform };
} else {
check(args[1], Match.Optional(Match.ObjectIncluding({
fields: Match.Optional(Match.OneOf(Object, undefined)),
sort: Match.Optional(Match.OneOf(Object, Array, Function, undefined)),
limit: Match.Optional(Match.OneOf(Number, undefined)),
skip: Match.Optional(Match.OneOf(Number, undefined))
})));
check(
args[1],
Match.Optional(
Match.ObjectIncluding({
fields: Match.Optional(Match.OneOf(Object, undefined)),
sort: Match.Optional(
Match.OneOf(Object, Array, Function, undefined)
),
limit: Match.Optional(Match.OneOf(Number, undefined)),
skip: Match.Optional(Match.OneOf(Number, undefined)),
})
)
);
return {
transform: self._transform,
@@ -386,31 +398,33 @@ Object.assign(Mongo.Collection.prototype, {
this._getFindSelector(args),
this._getFindOptions(args)
);
}
},
});
Object.assign(Mongo.Collection, {
_publishCursor(cursor, sub, collection) {
var observeHandle = cursor.observeChanges({
added: function (id, fields) {
sub.added(collection, id, fields);
var observeHandle = cursor.observeChanges(
{
added: function(id, fields) {
sub.added(collection, id, fields);
},
changed: function(id, fields) {
sub.changed(collection, id, fields);
},
removed: function(id) {
sub.removed(collection, id);
},
},
changed: function (id, fields) {
sub.changed(collection, id, fields);
},
removed: function (id) {
sub.removed(collection, id);
}
},
// Publications don't mutate the documents
// This is tested by the `livedata - publish callbacks clone` test
{ nonMutatingCallbacks: true });
// Publications don't mutate the documents
// This is tested by the `livedata - publish callbacks clone` test
{ nonMutatingCallbacks: true }
);
// We don't call sub.ready() here: it gets called in livedata_server, after
// possibly calling _publishCursor on multiple returned cursors.
// register stop callback (expects lambda w/ no args).
sub.onStop(function () {
sub.onStop(function() {
observeHandle.stop();
});
@@ -425,8 +439,7 @@ Object.assign(Mongo.Collection, {
// instead.
_rewriteSelector(selector, { fallbackId } = {}) {
// shorthand -- scalars match _id
if (LocalCollection._selectorIsId(selector))
selector = {_id: selector};
if (LocalCollection._selectorIsId(selector)) selector = { _id: selector };
if (Array.isArray(selector)) {
// This is consistent with the Mongo console itself; if we don't do this
@@ -434,13 +447,13 @@ Object.assign(Mongo.Collection, {
throw new Error("Mongo selector can't be an array.");
}
if (!selector || (('_id' in selector) && !selector._id)) {
if (!selector || ('_id' in selector && !selector._id)) {
// can't match anything
return { _id: fallbackId || Random.id() };
}
return selector;
}
},
});
Object.assign(Mongo.Collection.prototype, {
@@ -486,7 +499,7 @@ Object.assign(Mongo.Collection.prototype, {
insert(doc, callback) {
// Make sure we were passed a document to insert
if (!doc) {
throw new Error("insert requires an argument");
throw new Error('insert requires an argument');
}
// Make a shallow clone of the document, preserving its prototype.
@@ -496,11 +509,13 @@ Object.assign(Mongo.Collection.prototype, {
);
if ('_id' in doc) {
if (! doc._id ||
! (typeof doc._id === 'string' ||
doc._id instanceof Mongo.ObjectID)) {
if (
!doc._id ||
!(typeof doc._id === 'string' || doc._id instanceof Mongo.ObjectID)
) {
throw new Error(
"Meteor requires document _id fields to be non-empty strings or ObjectIDs");
'Meteor requires document _id fields to be non-empty strings or ObjectIDs'
);
}
} else {
let generateId = true;
@@ -522,7 +537,7 @@ Object.assign(Mongo.Collection.prototype, {
// On inserts, always return the id that we generated; on all other
// operations, just return the result from the collection.
var chooseReturnValueFromCollectionResult = function (result) {
var chooseReturnValueFromCollectionResult = function(result) {
if (doc._id) {
return doc._id;
}
@@ -536,10 +551,12 @@ Object.assign(Mongo.Collection.prototype, {
};
const wrappedCallback = wrapCallback(
callback, chooseReturnValueFromCollectionResult);
callback,
chooseReturnValueFromCollectionResult
);
if (this._isRemoteCollection()) {
const result = this._callMutatorMethod("insert", [doc], wrappedCallback);
const result = this._callMutatorMethod('insert', [doc], wrappedCallback);
return chooseReturnValueFromCollectionResult(result);
}
@@ -584,8 +601,13 @@ Object.assign(Mongo.Collection.prototype, {
if (options && options.upsert) {
// set `insertedId` if absent. `insertedId` is a Meteor extension.
if (options.insertedId) {
if (!(typeof options.insertedId === 'string' || options.insertedId instanceof Mongo.ObjectID))
throw new Error("insertedId must be string or ObjectID");
if (
!(
typeof options.insertedId === 'string' ||
options.insertedId instanceof Mongo.ObjectID
)
)
throw new Error('insertedId must be string or ObjectID');
insertedId = options.insertedId;
} else if (!selector || !selector._id) {
insertedId = this._makeNewID();
@@ -594,19 +616,16 @@ Object.assign(Mongo.Collection.prototype, {
}
}
selector =
Mongo.Collection._rewriteSelector(selector, { fallbackId: insertedId });
selector = Mongo.Collection._rewriteSelector(selector, {
fallbackId: insertedId,
});
const wrappedCallback = wrapCallback(callback);
if (this._isRemoteCollection()) {
const args = [
selector,
modifier,
options
];
const args = [selector, modifier, options];
return this._callMutatorMethod("update", args, wrappedCallback);
return this._callMutatorMethod('update', args, wrappedCallback);
}
// it's my collection. descend into the collection object
@@ -616,7 +635,11 @@ Object.assign(Mongo.Collection.prototype, {
// operation asynchronously, then queryRet will be undefined, and the
// result will be returned through the callback instead.
return this._collection.update(
selector, modifier, options, wrappedCallback);
selector,
modifier,
options,
wrappedCallback
);
} catch (e) {
if (callback) {
callback(e);
@@ -641,7 +664,7 @@ Object.assign(Mongo.Collection.prototype, {
const wrappedCallback = wrapCallback(callback);
if (this._isRemoteCollection()) {
return this._callMutatorMethod("remove", [selector], wrappedCallback);
return this._callMutatorMethod('remove', [selector], wrappedCallback);
}
// it's my collection. descend into the collection object
@@ -680,16 +703,21 @@ Object.assign(Mongo.Collection.prototype, {
* @param {Function} [callback] Optional. If present, called with an error object as the first argument and, if no error, the number of affected documents as the second.
*/
upsert(selector, modifier, options, callback) {
if (! callback && typeof options === "function") {
if (!callback && typeof options === 'function') {
callback = options;
options = {};
}
return this.update(selector, modifier, {
...options,
_returnObject: true,
upsert: true,
}, callback);
return this.update(
selector,
modifier,
{
...options,
_returnObject: true,
upsert: true,
},
callback
);
},
// We'll actually design an index API later. For now, we just pass through to
@@ -697,7 +725,7 @@ Object.assign(Mongo.Collection.prototype, {
_ensureIndex(index, options) {
var self = this;
if (!self._collection._ensureIndex || !self._collection.createIndex)
throw new Error("Can only call createIndex on server collections");
throw new Error('Can only call createIndex on server collections');
// TODO enable this message a release before we will remove this function
// import { Log } from 'meteor/logging';
// Log.debug(`_ensureIndex has been deprecated, please use the new 'createIndex' instead${options?.name ? `, index name: ${options.name}` : `, index: ${JSON.stringify(index)}`}`)
@@ -715,7 +743,7 @@ Object.assign(Mongo.Collection.prototype, {
* @memberof Mongo.Collection
* @instance
* @param {Object} index A document that contains the field and value pairs where the field is the index key and the value describes the type of index for that field. For an ascending index on a field, specify a value of `1`; for descending index, specify a value of `-1`. Use `text` for text indexes.
* @param {Object} [options] All options are listed in [MongoDB documentation](https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/#std-label-ensureIndex-options)
* @param {Object} [options] All options are listed in [MongoDB documentation](https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/#options)
* @param {String} options.name Name of the index
* @param {Boolean} options.unique Define that the index values must be unique, more at [MongoDB documentation](https://docs.mongodb.com/manual/core/index-unique/)
* @param {Boolean} options.sparse Define that the index is sparse, more at [MongoDB documentation](https://docs.mongodb.com/manual/core/index-sparse/)
@@ -723,28 +751,30 @@ Object.assign(Mongo.Collection.prototype, {
createIndex(index, options) {
var self = this;
if (!self._collection.createIndex)
throw new Error("Can only call createIndex on server collections");
throw new Error('Can only call createIndex on server collections');
self._collection.createIndex(index, options);
},
_dropIndex(index) {
var self = this;
if (!self._collection._dropIndex)
throw new Error("Can only call _dropIndex on server collections");
throw new Error('Can only call _dropIndex on server collections');
self._collection._dropIndex(index);
},
_dropCollection() {
var self = this;
if (!self._collection.dropCollection)
throw new Error("Can only call _dropCollection on server collections");
throw new Error('Can only call _dropCollection on server collections');
self._collection.dropCollection();
},
_createCappedCollection(byteSize, maxDocuments) {
var self = this;
if (!self._collection._createCappedCollection)
throw new Error("Can only call _createCappedCollection on server collections");
throw new Error(
'Can only call _createCappedCollection on server collections'
);
self._collection._createCappedCollection(byteSize, maxDocuments);
},
@@ -756,8 +786,8 @@ Object.assign(Mongo.Collection.prototype, {
*/
rawCollection() {
var self = this;
if (! self._collection.rawCollection) {
throw new Error("Can only call rawCollection on server collections");
if (!self._collection.rawCollection) {
throw new Error('Can only call rawCollection on server collections');
}
return self._collection.rawCollection();
},
@@ -770,24 +800,27 @@ Object.assign(Mongo.Collection.prototype, {
*/
rawDatabase() {
var self = this;
if (! (self._driver.mongo && self._driver.mongo.db)) {
throw new Error("Can only call rawDatabase on server collections");
if (!(self._driver.mongo && self._driver.mongo.db)) {
throw new Error('Can only call rawDatabase on server collections');
}
return self._driver.mongo.db;
}
},
});
// Convert the callback to not return a result if there is an error
function wrapCallback(callback, convertResult) {
return callback && function (error, result) {
if (error) {
callback(error);
} else if (typeof convertResult === "function") {
callback(error, convertResult(result));
} else {
callback(error, result);
return (
callback &&
function(error, result) {
if (error) {
callback(error);
} else if (typeof convertResult === 'function') {
callback(error, convertResult(result));
} else {
callback(error, result);
}
}
};
);
}
/**
@@ -821,17 +854,16 @@ Mongo.Collection.ObjectID = Mongo.ObjectID;
Meteor.Collection = Mongo.Collection;
// Allow deny stuff is now in the allow-deny package
Object.assign(
Meteor.Collection.prototype,
AllowDeny.CollectionPrototype
);
Object.assign(Meteor.Collection.prototype, AllowDeny.CollectionPrototype);
function popCallbackFromArgs(args) {
// Pull off any callback (or perhaps a 'callback' variable that was passed
// in undefined, like how 'upsert' does it).
if (args.length &&
(args[args.length - 1] === undefined ||
args[args.length - 1] instanceof Function)) {
if (
args.length &&
(args[args.length - 1] === undefined ||
args[args.length - 1] instanceof Function)
) {
return args.pop();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
node_modules/

View File

@@ -0,0 +1,19 @@
# This file contains information which helps Meteor properly upgrade your
# app when you run 'meteor update'. You should check it into version control
# with your project.
notices-for-0.9.0
notices-for-0.9.1
0.9.4-platform-file
notices-for-facebook-graph-api-2
1.2.0-standard-minifiers-package
1.2.0-meteor-platform-split
1.2.0-cordova-changes
1.2.0-breaking-changes
1.3.0-split-minifiers-package
1.4.0-remove-old-dev-bundle-link
1.4.1-add-shell-server-package
1.4.3-split-account-service-packages
1.5-add-dynamic-import-package
1.7-split-underscore-from-meteor-base
1.8.3-split-jquery-from-blaze

View File

@@ -0,0 +1 @@
local

View File

@@ -0,0 +1,7 @@
# This file contains a token that is unique to your project.
# Check it into your repository along with the rest of this directory.
# It can be used for purposes such as:
# - ensuring you don't accidentally deploy one app on top of another
# - providing package authors with aggregated statistics
y1s06jw2jowx.c256atzmooh5

View File

@@ -0,0 +1,23 @@
# Meteor packages used by this project, one per line.
# Check this file (and the other files in this directory) into your repository.
#
# 'meteor add' and 'meteor remove' will edit this file for you,
# but you can also edit it by hand.
meteor-base@1.5.1 # Packages every Meteor app needs to have
mobile-experience@1.1.0 # Packages for a great mobile UX
mongo@1.13.0 # The database Meteor supports right now
reactive-var@1.0.11 # Reactive variable for tracker
standard-minifier-css@1.7.4 # CSS minifier run for production mode
standard-minifier-js@2.7.0 # JS minifier run for production mode
es5-shim@4.8.0 # ECMAScript 5 compatibility for older browsers
ecmascript@0.15.3 # Enable ECMAScript2015+ syntax in app code
typescript@4.3.5 # Enable TypeScript syntax in .ts and .tsx modules
shell-server@0.5.0 # Server-side component of the `meteor shell` command
hot-module-replacement@0.3.0 # Update client in development without reloading the page
autopublish@1.0.7 # Publish all data to the clients (for prototyping)
insecure@1.0.7 # Allow all DB writes from clients (for prototyping)
static-html@1.3.2 # Define static page content in .html files
react-meteor-data # React higher-order component for reactively tracking Meteor data

View File

@@ -0,0 +1,2 @@
server
browser

View File

@@ -0,0 +1 @@
METEOR@2.4

View File

@@ -0,0 +1,78 @@
allow-deny@1.1.0
autopublish@1.0.7
autoupdate@1.7.0
babel-compiler@7.7.0
babel-runtime@1.5.0
base64@1.0.12
binary-heap@1.0.11
blaze-tools@1.1.2
boilerplate-generator@1.7.1
caching-compiler@1.2.2
caching-html-compiler@1.2.1
callback-hook@1.4.0
check@1.3.1
ddp@1.4.0
ddp-client@2.5.0
ddp-common@1.4.0
ddp-server@2.5.0
diff-sequence@1.1.1
dynamic-import@0.7.1
ecmascript@0.15.3
ecmascript-runtime@0.8.0
ecmascript-runtime-client@0.12.1
ecmascript-runtime-server@0.11.0
ejson@1.1.1
es5-shim@4.8.0
fetch@0.1.1
geojson-utils@1.0.10
hot-code-push@1.0.4
hot-module-replacement@0.3.0
html-tools@1.1.2
htmljs@1.1.1
http@1.0.10
id-map@1.1.1
insecure@1.0.7
inter-process-messaging@0.1.1
launch-screen@1.3.0
logging@1.3.1
meteor@1.10.0
meteor-base@1.5.1
meteortesting:browser-tests@1.3.4
meteortesting:mocha@2.0.3
meteortesting:mocha-core@8.0.1
minifier-css@1.6.0
minifier-js@2.7.1
minimongo@1.7.0
mobile-experience@1.1.0
mobile-status-bar@1.1.0
modern-browsers@0.1.7
modules@0.17.0
modules-runtime@0.12.0
modules-runtime-hot@0.13.0
mongo@1.13.0
mongo-decimal@0.1.2
mongo-dev-server@1.1.0
mongo-id@1.0.8
npm-mongo@3.9.1
ordered-dict@1.1.0
promise@0.12.0
random@1.2.0
react-fast-refresh@0.1.1
react-meteor-data@2.3.3
reactive-var@1.0.11
reload@1.3.1
retry@1.1.0
routepolicy@1.1.1
shell-server@0.5.0
socket-stream-client@0.4.0
spacebars-compiler@1.3.0
standard-minifier-css@1.7.4
standard-minifier-js@2.7.1
static-html@1.3.2
templating-tools@1.2.1
tracker@1.2.0
typescript@4.3.5
underscore@1.0.10
url@1.3.2
webapp@1.12.0
webapp-hashing@1.1.0

View File

@@ -0,0 +1,4 @@
body {
padding: 10px;
font-family: sans-serif;
}

View File

@@ -0,0 +1,7 @@
<head>
<title>escmascript-regression</title>
</head>
<body>
<div id="react-target"></div>
</body>

View File

@@ -0,0 +1,8 @@
import React from 'react';
import { Meteor } from 'meteor/meteor';
import { render } from 'react-dom';
import { App } from '/imports/ui/App';
Meteor.startup(() => {
render(<App/>, document.getElementById('react-target'));
});

View File

@@ -0,0 +1,9 @@
import React from 'react';
import { Hello } from './Hello.jsx';
export const App = () => (
<div>
<h1>Welcome to Meteor!</h1>
<Hello />
</div>
);

View File

@@ -0,0 +1,16 @@
import React, { useState } from 'react';
export const Hello = () => {
const [counter, setCounter] = useState(0);
const increment = () => {
setCounter(counter + 1);
};
return (
<div>
<button onClick={increment}>Click Me</button>
<p>You've pressed the button {counter} times.</p>
</div>
);
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
{
"name": "escmascript-regression",
"private": true,
"scripts": {
"start": "meteor run",
"test": "meteor test --driver-package meteortesting:mocha",
"test-app": "TEST_WATCH=1 meteor test --full-app --driver-package meteortesting:mocha --exclude-archs web.browser"
},
"dependencies": {
"@babel/runtime": "^7.15.3",
"meteor-node-stubs": "^1.1.0",
"puppeteer": "^10.4.0",
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"meteor": {
"mainModule": {
"client": "client/main.jsx",
"server": "server/main.js"
},
"testModule": "tests/main.js"
}
}

View File

@@ -0,0 +1 @@
import { Meteor } from 'meteor/meteor';

View File

@@ -0,0 +1,27 @@
import assert from 'assert';
describe('escmascript-regression', function() {
if (Meteor.isClient) {
it('NodeList spread', function() {
const div = document.createElement('div');
document.body.appendChild(div);
for (let i = 0; i < 5; i++) {
const child = document.createElement('div');
child.innerText = `child ${i}`;
div.appendChild(child);
}
try {
assert.strictEqual(div.childNodes?.length, 5);
const arr = [...div.childNodes];
arr.forEach((el, i) => {
assert.equal(el.innerText, `child ${i}`);
});
} finally {
document.body.removeChild(div);
}
});
}
});

View File

@@ -1,51 +1,54 @@
var selftest = require('../tool-testing/selftest.js');
var Sandbox = selftest.Sandbox;
var utils = require('../utils/utils.js');
import { getUrl } from '../utils/http-helpers.js';
var MONGO_LISTENING =
{ stdout: " [initandlisten] waiting for connections on port" };
var MONGO_LISTENING = {
stdout: ' [initandlisten] waiting for connections on port',
};
function startRun(sandbox) {
var run = sandbox.run();
run.match("myapp");
run.match("proxy");
run.match('myapp');
run.match('proxy');
run.tellMongo(MONGO_LISTENING);
run.waitSecs(20);
run.match("MongoDB");
run.match('MongoDB');
return run;
};
}
selftest.define("modules - test app", function () {
selftest.define('modules - test app', function() {
const s = new Sandbox();
// Make sure we use the right "env" section of .babelrc.
s.set("NODE_ENV", "development");
s.set('NODE_ENV', 'development');
// For meteortesting:mocha to work we must set test broswer driver
// For meteortesting:mocha to work we must set test browser driver
// See https://github.com/meteortesting/meteor-mocha
s.set("TEST_BROWSER_DRIVER", "puppeteer");
s.set('TEST_BROWSER_DRIVER', 'puppeteer');
s.createApp("modules-test-app", "modules");
s.cd("modules-test-app", function () {
s.createApp('modules-test-app', 'modules');
s.cd('modules-test-app', function() {
const run = s.run(
"test", "--once", "--full-app",
"--driver-package", "meteortesting:mocha"
'test',
'--once',
'--full-app',
'--driver-package',
'meteortesting:mocha'
);
run.waitSecs(60);
run.match("App running at");
run.match("SERVER FAILURES: 0");
run.match("CLIENT FAILURES: 0");
run.match('App running at');
run.match('SERVER FAILURES: 0');
run.match('CLIENT FAILURES: 0');
run.expectExit(0);
});
});
selftest.define("modules - unimported lazy files", function() {
selftest.define('modules - unimported lazy files', function() {
const s = new Sandbox();
s.createApp("myapp", "app-with-unimported-lazy-file");
s.cd("myapp", function() {
const run = s.run("--once");
s.createApp('myapp', 'app-with-unimported-lazy-file');
s.cd('myapp', function() {
const run = s.run('--once');
run.waitSecs(30);
run.expectExit(1);
run.forbid("This file shouldn't be loaded");
@@ -55,43 +58,47 @@ selftest.define("modules - unimported lazy files", function() {
// Checks that `import X from 'meteor/package'` will import (and re-export) the
// mainModule if one exists, otherwise will simply export Package['package'].
// Overlaps with compiler-plugin.js's "install-packages.js" code.
selftest.define("modules - import chain for packages", () => {
selftest.define('modules - import chain for packages', () => {
const s = new Sandbox({ fakeMongo: true });
s.createApp("myapp", "package-tests");
s.cd("myapp");
s.createApp('myapp', 'package-tests');
s.cd('myapp');
s.write(".meteor/packages", [
"meteor-base",
"modules",
"with-add-files",
"with-main-module",
""
].join("\n"));
s.write(
'.meteor/packages',
['meteor-base', 'modules', 'with-add-files', 'with-main-module', ''].join(
'\n'
)
);
s.write("main.js", [
"var packageNameA = require('meteor/with-add-files').name;",
"var packageNameB = require('meteor/with-main-module').name;",
"",
"console.log('with-add-files: ' + packageNameA);",
"console.log('with-main-module: ' + packageNameB);",
""
].join("\n"));
s.write(
'main.js',
[
"var packageNameA = require('meteor/with-add-files').name;",
"var packageNameB = require('meteor/with-main-module').name;",
'',
"console.log('with-add-files: ' + packageNameA);",
"console.log('with-main-module: ' + packageNameB);",
'',
].join('\n')
);
const run = startRun(s);
run.waitSecs(30);
// On the server, we just check that importing *works*, not *how* it works
run.match("with-add-files: with-add-files");
run.match("with-main-module: with-main-module");
run.match('with-add-files: with-add-files');
run.match('with-main-module: with-main-module');
// On the client, we just check that install() is called correctly
checkModernAndLegacyUrls("/packages/modules.js", body => {
checkModernAndLegacyUrls('/packages/modules.js', body => {
selftest.expectTrue(body.includes('\ninstall("with-add-files");'));
selftest.expectTrue(
body.includes('\ninstall("with-main-module", ' +
'"meteor/with-main-module/with-main-module.js");')
body.includes(
'\ninstall("with-main-module", ' +
'"meteor/with-main-module/with-main-module.js");'
)
);
});
@@ -99,9 +106,9 @@ selftest.define("modules - import chain for packages", () => {
});
function checkModernAndLegacyUrls(path, test) {
if (! path.startsWith("/")) {
path = "/" + path;
if (!path.startsWith('/')) {
path = '/' + path;
}
test(getUrl("http://localhost:3000" + path));
test(getUrl("http://localhost:3000/__browser.legacy" + path));
test(getUrl('http://localhost:3000' + path));
test(getUrl('http://localhost:3000/__browser.legacy' + path));
}

View File

@@ -0,0 +1,32 @@
var selftest = require('../tool-testing/selftest.js');
var Sandbox = selftest.Sandbox;
selftest.define('regressions - web.browser.legacy', function() {
const s = new Sandbox();
// Make sure we use the right "env" section of .babelrc.
s.set('NODE_ENV', 'development');
// For meteortesting:mocha to work we must set test browser driver
// See https://github.com/meteortesting/meteor-mocha
s.set('TEST_BROWSER_DRIVER', 'puppeteer');
s.createApp('modules-test-app', 'ecmascript-regression');
s.cd('modules-test-app', function() {
const run = s.run(
'test',
'--once',
'--full-app',
'--driver-package',
'meteortesting:mocha',
'--exclude-archs',
'web.browser'
);
run.waitSecs(60);
run.match('App running at');
run.match('SERVER FAILURES: 0');
run.match('CLIENT FAILURES: 0');
run.expectExit(0);
});
});