diff --git a/History.md b/History.md index 9ded11a003..0a00833214 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,25 @@ ## vNEXT +## v0.6.5.1 + +* Fix syntax errors on lines that end with a backslash. #1326 + +* Fix serving static files with special characters in their name. #1339 + +* Upgrade `esprima` JavaScript parser to fix bug parsing complex regexps. + +* Export `Spiderable` from `spiderable` package to allow users to set + `Spiderable.userAgentRegExps` to control what user agents are treated + as spiders. + +* Add EJSON to standard-app-packages. #1343 + +* Fix bug in d3 tab character parsing. + +* Fix regression when using Mongo ObjectIDs in Spark templates. + + ## v0.6.5 * New package system with package compiler and linker: diff --git a/docs/.meteor/release b/docs/.meteor/release index ef5e445445..3f50c3b805 100644 --- a/docs/.meteor/release +++ b/docs/.meteor/release @@ -1 +1 @@ -0.6.5 +galaxy-appconfig-2 diff --git a/docs/client/api.html b/docs/client/api.html index cc75bdc559..5d30aec68c 100644 --- a/docs/client/api.html +++ b/docs/client/api.html @@ -2409,7 +2409,7 @@ from the call to `check` or `Match.test`. Examples: NonEmptyString = Match.Where(function (x) { check(x, String); return x.length > 0; - } + }); check(arg, NonEmptyString); {{/dtdd}} diff --git a/docs/client/concepts.html b/docs/client/concepts.html index 9626162e93..f0c59d774f 100644 --- a/docs/client/concepts.html +++ b/docs/client/concepts.html @@ -724,7 +724,7 @@ might have two or three (for example, a package that provides several classes that work together). You see only the exports of the packages that you use directly. If you -use package A, and package B uses package A, then you only see package +use package A, and package A uses package B, then you only see package A's exports. Package B's exports don't "leak" into your namespace just because you used package A. This keeps each namespace nice and tidy. Each app or package only sees their own globals plus the APIs of @@ -752,6 +752,17 @@ debugger, you've got two options: you can access `Package.email.Email.send` even from namespaces that don't use the `email` package directly. +When declaring functions, keep in mind that `function x () {}` is just +shorthard for `var x = function () {}` in JavaScript. Consider these +examples: + + // This is the same as 'var x = function () ...'. So x() is + // file-scope and can be called only from within this one file. + function x () { ... } + + // No 'var', so x() is package-scope and can be called from + // any file inside this app or package. + x = function () { ... } {{#note}} Technically speaking, globals in an app (as opposed to in a package) @@ -831,7 +842,7 @@ created on. To run on a different platform, you'll need to rebuild the native packages included in the bundle. To do that, make sure you have `npm` available, and run the following: - $ cd bundle/server/node_modules + $ cd bundle/programs/server/node_modules $ rm -r fibers $ npm install fibers@1.0.1 {{/warning}} @@ -924,14 +935,14 @@ quick tips: to load before A. This is occasionally useful for resolving circular dependencies. -* It is also for one package to imply another package with - `api.imply`. If package A implies package B, then when someone - depends on package A, it's as if they also depended on package B as - well. In particular, they get B's exports. This can be used to - create umbrella packages such as `standard-app-packages` that are a - shortcut for pulling in a set of packages, or it can be helpful in - factoring common code out of a set of packages as with - `accounts-base`. +* The build system also supports package implication. If package A + implies package B, then it means that when someone depends on + package A, it's as if they also depended on package B as well. In + particular, they get B's exports. This is done with `api.imply` and + can be used to create umbrella packages such as + `standard-app-packages` that are a shortcut for pulling in a set of + packages, or it can be helpful in factoring common code out of a set + of packages as with `accounts-base`. * The build system understands the idea of native code and has a system of architecture names to ensure that packages that are diff --git a/docs/client/docs.js b/docs/client/docs.js index dfa8773234..c057ef71bd 100644 --- a/docs/client/docs.js +++ b/docs/client/docs.js @@ -1,5 +1,8 @@ Template.headline.release = function () { - return Meteor.release || "(checkout)"; + // XXX This is commented out because for now galaxy apps have to be on a + // different Meteor release that has a bug fix. + return "0.6.5.1"; + // return Meteor.release || "(checkout)"; }; diff --git a/docs/client/packages/coffeescript.html b/docs/client/packages/coffeescript.html index 08e09c3e9c..d01284cf4f 100644 --- a/docs/client/packages/coffeescript.html +++ b/docs/client/packages/coffeescript.html @@ -11,5 +11,42 @@ CoffeeScript is supported on both the client and the server. Files ending with `.coffee` or `.litcoffee` are automatically compiled to JavaScript. +### Namespacing and CoffeeScript + +Here's how CoffeeScript works with Meteor's namespacing. + +* Per the usual CoffeeScript convention, CoffeeScript variable are + file-scoped by default (visible only in the `.coffee` file where + they are defined.) + +* When writing a package, CoffeeScript-defined variables can be + exported like any other variable (see [Writing + Packages](#writingpackages)). Exporting a variable pulls it up to + package scope, meaning that it will be visible to all of the code in + your app or package (both `.js` and `.coffee` files). + +* Package-scope variables declared in `.js` files are visible in any + `.coffee` files in the same app or project. + +* There is no way to make a package-scope variable from a `.coffee` + file other than exporting it. We couldn't figure out a way to make + this fit naturally inside the CoffeeScript language. If you want to + use package-scope variables with CoffeeScript, one way is to make a + short `.js` file that declares all of your package-scope + variables. They can then be used and assigned to from `.coffee` + files. + +* If you want to share variables between `.coffee` files in the same + package, and don't want to separately declare them in a `.js` file, + we have an experimental feature that you may like. An object called + `share` is visible in CoffeeScript code and is shared across all + `.coffee` files in the same package. So, you can write `share.foo` + for a value that is shared between all CoffeeScript code in a + package, but doesn't escape that package. + +Heavy CoffeeScript users, please let us know how this arrangement +works for you, whether `share` is helpful for you, and anything else +you'd like to see changed. + {{/better_markdown}} diff --git a/examples/leaderboard/.meteor/release b/examples/leaderboard/.meteor/release index ef5e445445..dd8bfff626 100644 --- a/examples/leaderboard/.meteor/release +++ b/examples/leaderboard/.meteor/release @@ -1 +1 @@ -0.6.5 +0.6.5.1 diff --git a/examples/parties/.meteor/release b/examples/parties/.meteor/release index ef5e445445..dd8bfff626 100644 --- a/examples/parties/.meteor/release +++ b/examples/parties/.meteor/release @@ -1 +1 @@ -0.6.5 +0.6.5.1 diff --git a/examples/todos/.meteor/release b/examples/todos/.meteor/release index ef5e445445..dd8bfff626 100644 --- a/examples/todos/.meteor/release +++ b/examples/todos/.meteor/release @@ -1 +1 @@ -0.6.5 +0.6.5.1 diff --git a/examples/wordplay/.meteor/release b/examples/wordplay/.meteor/release index ef5e445445..dd8bfff626 100644 --- a/examples/wordplay/.meteor/release +++ b/examples/wordplay/.meteor/release @@ -1 +1 @@ -0.6.5 +0.6.5.1 diff --git a/packages/amplify/package.js b/packages/amplify/package.js index c808eda438..012777f8b1 100644 --- a/packages/amplify/package.js +++ b/packages/amplify/package.js @@ -1,5 +1,5 @@ Package.describe({ - summary: "API for Persistant Storage, PubSub and Request" + summary: "API for Persistent Storage, PubSub and Request" }); Package.on_use(function (api) { diff --git a/packages/d3/d3.v3.js b/packages/d3/d3.v3.js index 08aff88cea..361a3e113e 100644 --- a/packages/d3/d3.v3.js +++ b/packages/d3/d3.v3.js @@ -1789,7 +1789,7 @@ d3 = function() { return dsv; } d3.csv = d3_dsv(",", "text/csv"); - d3.tsv = d3_dsv(" ", "text/tab-separated-values"); + d3.tsv = d3_dsv("\t", "text/tab-separated-values"); var d3_timer_id = 0, d3_timer_byId = {}, d3_timer_queue = null, d3_timer_interval, d3_timer_timeout; d3.timer = function(callback, delay, then) { if (arguments.length < 3) { diff --git a/packages/handlebars/evaluate-handlebars.js b/packages/handlebars/evaluate-handlebars.js index fa3df9bcd2..ab895c2550 100644 --- a/packages/handlebars/evaluate-handlebars.js +++ b/packages/handlebars/evaluate-handlebars.js @@ -12,6 +12,13 @@ Handlebars.json_ast_to_func = function (ast) { }; }; +// If minimongo is available (it's a weak dependency) use its ID stringifier to +// label branches (so that, eg, ObjectId and strings don't overlap). Otherwise +// just use the identity function. +var idStringify = Package.minimongo + ? Package.minimongo.LocalCollection._idStringify + : function (id) { return id; }; + // block helpers take: // (N args), options (hash args, plus 'fn' and 'inverse') // and return text @@ -38,7 +45,8 @@ Handlebars._default_helpers = { if (data && data.length > 0) return _.map(data, function(x, i) { // infer a branch key from the data - var branch = ((x && x._id) || (typeof x === 'string' ? x : null) || + var branch = ((x && x._id && idStringify(x._id)) || + (typeof x === 'string' ? x : null) || Spark.UNIQUE_LABEL); return Spark.labelBranch(branch, function() { return options.fn(x); diff --git a/packages/handlebars/package.js b/packages/handlebars/package.js index 90e3631cce..dfbecc219f 100644 --- a/packages/handlebars/package.js +++ b/packages/handlebars/package.js @@ -11,6 +11,10 @@ Package.on_use(function (api) { api.export('Handlebars'); + + // If we have minimongo available, use its idStringify function. + api.use('minimongo', 'client', {weak: true}); + // XXX these should be split up into two different slices, not // different code with totally different APIs that is sent depending // on the architecture diff --git a/packages/js-analyze/.npm/package/npm-shrinkwrap.json b/packages/js-analyze/.npm/package/npm-shrinkwrap.json index 04b9946958..52f2263019 100644 --- a/packages/js-analyze/.npm/package/npm-shrinkwrap.json +++ b/packages/js-analyze/.npm/package/npm-shrinkwrap.json @@ -1,7 +1,7 @@ { "dependencies": { "esprima": { - "from": "https://github.com/ariya/esprima/tarball/5044b87f94fb802d9609f1426c838874ec2007b3" + "from": "https://github.com/ariya/esprima/tarball/2a41dbf0ddadade0b09a9a7cc9a0c8df9c434018" }, "estraverse": { "version": "1.1.2-1" diff --git a/packages/js-analyze/package.js b/packages/js-analyze/package.js index 71087fefc3..8bc4b460b6 100644 --- a/packages/js-analyze/package.js +++ b/packages/js-analyze/package.js @@ -13,7 +13,7 @@ Package.describe({ Npm.depends({ // This code was originally written against the unreleased 1.1 branch. We can // probably switch to a built NPM version when it gets released. - esprima: "https://github.com/ariya/esprima/tarball/5044b87f94fb802d9609f1426c838874ec2007b3", + esprima: "https://github.com/ariya/esprima/tarball/2a41dbf0ddadade0b09a9a7cc9a0c8df9c434018", estraverse: "1.1.2-1", // Fork to add ignoreEval option. // https://github.com/Constellation/escope/pull/18 diff --git a/packages/minimongo/minimongo.js b/packages/minimongo/minimongo.js index d50b9de011..7787977f10 100644 --- a/packages/minimongo/minimongo.js +++ b/packages/minimongo/minimongo.js @@ -427,7 +427,7 @@ LocalCollection.prototype.insert = function (doc, callback) { } var id = LocalCollection._idStringify(doc._id); - if (_.has(self.docs, doc._id)) + if (_.has(self.docs, id)) throw MinimongoError("Duplicate _id '" + doc._id + "'"); self._saveOriginal(id, undefined); diff --git a/packages/spark/convenience.js b/packages/spark/convenience.js index e4b3c3f81a..a8e5a82fb6 100644 --- a/packages/spark/convenience.js +++ b/packages/spark/convenience.js @@ -11,7 +11,8 @@ Meteor.render = function (htmlFunc) { Meteor.renderList = function (cursor, itemFunc, elseFunc) { return Spark.render(function () { return Spark.list(cursor, function (item) { - return Spark.labelBranch(item._id || null, function () { + var label = item._id ? idStringify(item._id) : null; + return Spark.labelBranch(label, function () { return Spark.isolate(_.bind(itemFunc, null, item)); }); }, function () { diff --git a/packages/spark/package.js b/packages/spark/package.js index afcbc42d58..8b2f8fbeb5 100644 --- a/packages/spark/package.js +++ b/packages/spark/package.js @@ -8,6 +8,9 @@ Package.on_use(function (api) { 'ordered-dict', 'deps', 'ejson'], 'client'); + // If we have minimongo available, use its idStringify function. + api.use('minimongo', 'client', {weak: true}); + api.export('Spark', 'client'); api.export('SparkTest', 'client', {testOnly: true}); diff --git a/packages/spark/spark.js b/packages/spark/spark.js index 7c3cf27911..2055cc7a67 100644 --- a/packages/spark/spark.js +++ b/packages/spark/spark.js @@ -903,18 +903,13 @@ var applyChanges = function (doc, changeFields) { }; -var idStringify; - -if (typeof LocalCollection !== 'undefined') { - idStringify = function (id) { - if (id === null) - return id; - else - return LocalCollection._idStringify(id); - }; -} else { - idStringify = function (id) { return id; }; -} +// If minimongo is available (it's a weak dependency) use its ID stringifier (so +// that, eg, ObjectId and strings don't overlap). Otherwise just use the +// identity function. +// This is also used in convenience.js. +idStringify = Package.minimongo + ? Package.minimongo.LocalCollection._idStringify + : function (id) { return id; }; Spark.list = function (cursor, itemFunc, elseFunc) { elseFunc = elseFunc || function () { return ''; }; diff --git a/packages/spiderable/package.js b/packages/spiderable/package.js index 425c2ae8bb..431cc5c77e 100644 --- a/packages/spiderable/package.js +++ b/packages/spiderable/package.js @@ -7,6 +7,8 @@ Package.on_use(function (api) { api.use(['templating'], 'client'); api.use(['underscore'], ['client', 'server']); + api.export('Spiderable', 'server'); + api.add_files('spiderable.html', 'client'); api.add_files('spiderable.js', 'server'); }); diff --git a/packages/spiderable/spiderable.js b/packages/spiderable/spiderable.js index 2e5bd04c4a..9bc8f8118f 100644 --- a/packages/spiderable/spiderable.js +++ b/packages/spiderable/spiderable.js @@ -9,7 +9,13 @@ Spiderable = {}; // not obey the _escaped_fragment_ protocol. The page is served // statically to any client whos user agent matches any of these // regexps. Users may modify this array. -Spiderable.userAgentRegExps = [/^facebookexternalhit/i, /^linkedinbot/i]; +// +// An original goal with the spiderable package was to avoid doing +// user-agent based tests. But the reality is not enough bots support +// the _escaped_fragment_ protocol, so we need to hardcode a list +// here. I shed a silent tear. +Spiderable.userAgentRegExps = [ + /^facebookexternalhit/i, /^linkedinbot/i, /^twitterbot/i]; // how long to let phantomjs run before we kill it var REQUEST_TIMEOUT = 15*1000; diff --git a/packages/standard-app-packages/package.js b/packages/standard-app-packages/package.js index eeb12c1574..147674e8e5 100644 --- a/packages/standard-app-packages/package.js +++ b/packages/standard-app-packages/package.js @@ -38,6 +38,8 @@ Package.on_use(function(api) { // $(".usefulToo") 'jquery', // Life isn't always predictable. - 'random' + 'random', + // People like being able to clone objects. + 'ejson' ]); }); diff --git a/packages/templating/deftemplate.js b/packages/templating/deftemplate.js index ad27795451..7aafefcb1b 100644 --- a/packages/templating/deftemplate.js +++ b/packages/templating/deftemplate.js @@ -2,6 +2,13 @@ Template = {}; var registeredPartials = {}; +// If minimongo is available (it's a weak dependency) use its ID stringifier to +// label branches (so that, eg, ObjectId and strings don't overlap). Otherwise +// just use the identity function. +var idStringify = Package.minimongo + ? Package.minimongo.LocalCollection._idStringify + : function (id) { return id; }; + // XXX Handlebars hooking is janky and gross var hookHandlebars = function () { hookHandlebars = function(){}; // install the hook only once @@ -17,7 +24,7 @@ var hookHandlebars = function () { arg, function (item) { return Spark.labelBranch( - (item && item._id) || Spark.UNIQUE_LABEL, function () { + (item && item._id && idStringify(item._id)) || Spark.UNIQUE_LABEL, function () { var html = Spark.isolate(_.bind(options.fn, null, item)); return Spark.setDataContext(item, html); }); diff --git a/packages/templating/package.js b/packages/templating/package.js index 702ef253d2..1dc56a6de7 100644 --- a/packages/templating/package.js +++ b/packages/templating/package.js @@ -26,6 +26,9 @@ Package.on_use(function (api) { api.export('Template', 'client'); + + // If we have minimongo available, use its idStringify function. + api.use('minimongo', 'client', {weak: true}); // provides the runtime logic to instantiate our templates api.add_files('deftemplate.js', 'client'); diff --git a/packages/webapp/webapp_server.js b/packages/webapp/webapp_server.js index d167942557..a3fc604ab1 100644 --- a/packages/webapp/webapp_server.js +++ b/packages/webapp/webapp_server.js @@ -234,10 +234,14 @@ var runWebAppServer = function () { // Auto-compress any json, javascript, or text. app.use(connect.compress()); + var getItemPathname = function (itemUrl) { + return decodeURIComponent(url.parse(itemUrl).pathname); + }; + var staticFiles = {}; _.each(clientJson.manifest, function (item) { if (item.url && item.where === "client") { - staticFiles[url.parse(item.url).pathname] = { + staticFiles[getItemPathname(item.url)] = { path: item.path, cacheable: item.cacheable, // Link from source to its map @@ -247,7 +251,7 @@ var runWebAppServer = function () { if (item.sourceMap) { // Serve the source map too, under the specified URL. We assume all // source maps are cacheable. - staticFiles[url.parse(item.sourceMapUrl).pathname] = { + staticFiles[getItemPathname(item.sourceMapUrl)] = { path: item.sourceMap, cacheable: true }; diff --git a/scripts/admin/banner.txt b/scripts/admin/banner.txt index 8947659e2e..f0422b945e 100644 --- a/scripts/admin/banner.txt +++ b/scripts/admin/banner.txt @@ -1,4 +1,5 @@ -=> Meteor 0.6.5: namespacing, modularity, new build system, source maps! +=> Meteor 0.6.5.1: a few bugfixes, including fixes for lines ending with + backslashes, filenames with with spaces, and tab characters in d3. This is being downloaded in the background. Update your project - to Meteor 0.6.5 by running 'meteor update'. + to Meteor 0.6.5.1 by running 'meteor update'. diff --git a/scripts/admin/notices.json b/scripts/admin/notices.json index 7eea43698d..176e5eb606 100644 --- a/scripts/admin/notices.json +++ b/scripts/admin/notices.json @@ -51,6 +51,9 @@ "https://docs.meteor.com/#writingpackages" ] }, + { + "release": "0.6.5.1" + }, { "release": "NEXT" } diff --git a/tools/linker.js b/tools/linker.js index 8392d28877..6d12925d51 100644 --- a/tools/linker.js +++ b/tools/linker.js @@ -355,7 +355,7 @@ _.extend(File.prototype, { _.each(lines, function (line) { var suffix = "\n"; - if (line.length <= width) { + if (line.length <= width && line[line.length - 1] !== "\\") { suffix = padding.slice(line.length, width) + " // " + num + "\n"; } f(line, suffix, num);