mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-05 20:32:00 -05:00
parent
c479ec9272
commit
46f415ca81
2 changed files with 74 additions and 49 deletions
|
@ -95,8 +95,6 @@ Base.exports.PaperScript = (function() {
|
||||||
return scope.acorn.parse(code, options);
|
return scope.acorn.parse(code, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
var sourceMaps = {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compiles PaperScript code into JavaScript code.
|
* Compiles PaperScript code into JavaScript code.
|
||||||
*
|
*
|
||||||
|
@ -104,13 +102,14 @@ Base.exports.PaperScript = (function() {
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* @option options.url {String} the url of the source, for source-map
|
* @option options.url {String} the url of the source, for source-map
|
||||||
* debugging
|
* generation
|
||||||
* @option options.source {String} the source to be used for the source-
|
* @option options.source {String} the source to be used for the source-
|
||||||
* mapping, in case the code that's passed in has already been mingled.
|
* mapping, in case the code that's passed in has already been mingled.
|
||||||
*
|
*
|
||||||
* @param {String} code the PaperScript code
|
* @param {String} code the PaperScript code
|
||||||
* @param {Object} [option] the compilation options
|
* @param {Object} [option] the compilation options
|
||||||
* @return {String} the compiled PaperScript translated into JavaScript code
|
* @return {Object} an object holding the compiled PaperScript translated
|
||||||
|
* into JavaScript code along with source-maps and other information.
|
||||||
*/
|
*/
|
||||||
function compile(code, options) {
|
function compile(code, options) {
|
||||||
if (!code)
|
if (!code)
|
||||||
|
@ -285,21 +284,23 @@ Base.exports.PaperScript = (function() {
|
||||||
agent = paper.agent,
|
agent = paper.agent,
|
||||||
version = agent.versionNumber,
|
version = agent.versionNumber,
|
||||||
offsetCode = false,
|
offsetCode = false,
|
||||||
sourceMap = null,
|
sourceMaps = options.sourceMaps,
|
||||||
// Include the original code in the sourceMap if there is no linked
|
// Include the original code in the sourceMap if there is no linked
|
||||||
// source file so the debugger can still display it correctly.
|
// source file so the debugger can still display it correctly.
|
||||||
source = options.source || code,
|
source = options.source || code,
|
||||||
lineBreaks = /\r\n|\n|\r/mg,
|
lineBreaks = /\r\n|\n|\r/mg,
|
||||||
offset = 0;
|
offset = options.offset || 0,
|
||||||
|
map;
|
||||||
// TODO: Verify these browser versions for source map support, and check
|
// TODO: Verify these browser versions for source map support, and check
|
||||||
// other browsers.
|
// other browsers.
|
||||||
if (agent.chrome && version >= 30
|
if (sourceMaps && (agent.chrome && version >= 30
|
||||||
|| agent.webkit && version >= 537.76 // >= Safari 7.0.4
|
|| agent.webkit && version >= 537.76 // >= Safari 7.0.4
|
||||||
|| agent.firefox && version >= 23
|
|| agent.firefox && version >= 23
|
||||||
|| agent.node) {
|
|| agent.node)) {
|
||||||
if (agent.node) {
|
if (agent.node) {
|
||||||
code = 'require("source-map-support").install(paper.PaperScript.sourceMapSupport);\n' + code;
|
// -2 required to remove function header:
|
||||||
offset = -3; // -2 for function body, - 1 for require("source-map-support")
|
// https://code.google.com/p/chromium/issues/detail?id=331655
|
||||||
|
offset -= 2;
|
||||||
} else if (url && window.location.href.indexOf(url) === 0) {
|
} else if (url && window.location.href.indexOf(url) === 0) {
|
||||||
// If the code stems from the actual html page, determine the
|
// If the code stems from the actual html page, determine the
|
||||||
// offset of inlined code.
|
// offset of inlined code.
|
||||||
|
@ -309,18 +310,21 @@ Base.exports.PaperScript = (function() {
|
||||||
offset = html.substr(0, html.indexOf(code) + 1).match(
|
offset = html.substr(0, html.indexOf(code) + 1).match(
|
||||||
lineBreaks).length + 1;
|
lineBreaks).length + 1;
|
||||||
}
|
}
|
||||||
// A hack required by most versions of browsers except chrome 36+:
|
// A hack required by older versions of browsers to align inlined
|
||||||
// Instead of starting the mappings at the given offset, we have to
|
// code: Instead of starting the mappings at the given offset, we
|
||||||
// shift the actual code down to the place in the original file, as
|
// have to shift the actual code down to the place in the original
|
||||||
// source-map support seems incomplete in these browsers.
|
// file, as source-map support seems incomplete in these browsers.
|
||||||
// TODO: Report as bugs?
|
offsetCode = offset > 0 && !(
|
||||||
offsetCode = offset > 0 && (!browser.chrome || version < 36);
|
agent.chrome && version >= 36 ||
|
||||||
|
agent.safari && version >= 600 ||
|
||||||
|
agent.firefox && version >= 40 ||
|
||||||
|
agent.node);
|
||||||
var mappings = ['AA' + encodeVLQ(offsetCode ? 0 : offset) + 'A'];
|
var mappings = ['AA' + encodeVLQ(offsetCode ? 0 : offset) + 'A'];
|
||||||
// Create empty entries by the amount of lines + 1, so join can be
|
// Create empty entries by the amount of lines + 1, so join can be
|
||||||
// used below to produce the actual instructions that many times.
|
// used below to produce the actual instructions that many times.
|
||||||
mappings.length = (code.match(lineBreaks) || []).length + 1
|
mappings.length = (code.match(lineBreaks) || []).length + 1
|
||||||
+ (offsetCode ? offset : 0);
|
+ (offsetCode ? offset : 0);
|
||||||
sourceMap = {
|
map = {
|
||||||
version: 3,
|
version: 3,
|
||||||
file: url,
|
file: url,
|
||||||
names:[],
|
names:[],
|
||||||
|
@ -328,6 +332,7 @@ Base.exports.PaperScript = (function() {
|
||||||
// the lines of the original code, all that is required is a
|
// the lines of the original code, all that is required is a
|
||||||
// mappings string that increments by one between each line.
|
// mappings string that increments by one between each line.
|
||||||
// AACA is the instruction to increment the line by one.
|
// AACA is the instruction to increment the line by one.
|
||||||
|
// TODO: Add support for column offsets!
|
||||||
mappings: mappings.join(';AACA'),
|
mappings: mappings.join(';AACA'),
|
||||||
sourceRoot: '',
|
sourceRoot: '',
|
||||||
sources: [url],
|
sources: [url],
|
||||||
|
@ -336,19 +341,25 @@ Base.exports.PaperScript = (function() {
|
||||||
}
|
}
|
||||||
// Now do the parsing magic
|
// Now do the parsing magic
|
||||||
walkAST(parse(code, { ranges: true }));
|
walkAST(parse(code, { ranges: true }));
|
||||||
if (sourceMap) {
|
if (map) {
|
||||||
// Adjust the line offset of the resulting code if required.
|
if (offsetCode) {
|
||||||
// This is part of a browser hack, see above.
|
// Adjust the line offset of the resulting code if required.
|
||||||
if (offsetCode)
|
// This is part of a browser hack, see above.
|
||||||
code = new Array(offset + 1).join('\n') + code;
|
code = new Array(offset + 1).join('\n') + code;
|
||||||
code += "\n//# sourceMappingURL=data:application/json;base64,"
|
}
|
||||||
+ window.btoa(unescape(encodeURIComponent(
|
if (/^(inline|both)$/.test(sourceMaps)) {
|
||||||
JSON.stringify(sourceMap))))
|
code += "\n//# sourceMappingURL=data:application/json;base64,"
|
||||||
+ "\n//# sourceURL=" + (url || 'paperscript');
|
+ window.btoa(unescape(encodeURIComponent(
|
||||||
if (url)
|
JSON.stringify(map))));
|
||||||
sourceMaps[url] = sourceMap;
|
}
|
||||||
|
code += "\n//# sourceURL=" + (url || 'paperscript');
|
||||||
}
|
}
|
||||||
return code;
|
return {
|
||||||
|
url: url,
|
||||||
|
source: source,
|
||||||
|
code: code,
|
||||||
|
map: map
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -362,14 +373,15 @@ Base.exports.PaperScript = (function() {
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* @option options.url {String} the url of the source, for source-map
|
* @option options.url {String} the url of the source, for source-map
|
||||||
* debugging
|
* generation
|
||||||
* @option options.source {String} the source to be used for the source-
|
* @option options.source {String} the source to be used for the source-
|
||||||
* mapping, in case the code that's passed in has already been mingled.
|
* mapping, in case the code that's passed in has already been mingled.
|
||||||
*
|
*
|
||||||
* @param {String} code the PaperScript code
|
* @param {String} code the PaperScript code
|
||||||
* @param {PaperScope} scope the scope for which the code is executed
|
* @param {PaperScope} scope the scope for which the code is executed
|
||||||
* @param {Object} [option] the compilation options
|
* @param {Object} [option] the compilation options
|
||||||
* @return {String} the compiled PaperScript translated into JavaScript code
|
* @return {Object} an object holding the compiled PaperScript translated
|
||||||
|
* into JavaScript code along with source-maps and other information.
|
||||||
*/
|
*/
|
||||||
function execute(code, scope, options) {
|
function execute(code, scope, options) {
|
||||||
// Set currently active scope.
|
// Set currently active scope.
|
||||||
|
@ -393,8 +405,9 @@ Base.exports.PaperScript = (function() {
|
||||||
// function call.
|
// function call.
|
||||||
params = [],
|
params = [],
|
||||||
args = [],
|
args = [],
|
||||||
func;
|
func,
|
||||||
code = compile(code, options);
|
compiled = typeof code === 'object' ? code : compile(code, options);
|
||||||
|
code = compiled.code;
|
||||||
function expose(scope, hidden) {
|
function expose(scope, hidden) {
|
||||||
// Look through all enumerable properties on the scope and expose
|
// Look through all enumerable properties on the scope and expose
|
||||||
// these too as pseudo-globals, but only if they seem to be in use.
|
// these too as pseudo-globals, but only if they seem to be in use.
|
||||||
|
@ -428,12 +441,12 @@ Base.exports.PaperScript = (function() {
|
||||||
if (handlers)
|
if (handlers)
|
||||||
code += '\nreturn { ' + handlers + ' };';
|
code += '\nreturn { ' + handlers + ' };';
|
||||||
var agent = paper.agent;
|
var agent = paper.agent;
|
||||||
if (agent.chrome || agent.firefox) {
|
if (agent.chrome || agent.firefox && agent.versionNumber < 40) {
|
||||||
// On Firefox, all error numbers inside dynamically compiled code
|
// On older Firefox, all error numbers inside dynamically compiled
|
||||||
// are relative to the line where the eval / compilation happened.
|
// code are relative to the line where the eval / compilation
|
||||||
// To fix this issue, we're temporarily inserting a new script
|
// happened. To fix this issue, we're temporarily inserting a new
|
||||||
// tag. We also use this on Chrome to fix an issue with compiled
|
// script tag.
|
||||||
// functions:
|
// We also use this on Chrome to fix issues with compiled functions:
|
||||||
// https://code.google.com/p/chromium/issues/detail?id=331655
|
// https://code.google.com/p/chromium/issues/detail?id=331655
|
||||||
var script = document.createElement('script'),
|
var script = document.createElement('script'),
|
||||||
head = document.head || document.getElementsByTagName('head')[0];
|
head = document.head || document.getElementsByTagName('head')[0];
|
||||||
|
@ -472,6 +485,7 @@ Base.exports.PaperScript = (function() {
|
||||||
// Automatically update view at the end.
|
// Automatically update view at the end.
|
||||||
view.update();
|
view.update();
|
||||||
}
|
}
|
||||||
|
return compiled;
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadScript(script) {
|
function loadScript(script) {
|
||||||
|
@ -562,13 +576,7 @@ Base.exports.PaperScript = (function() {
|
||||||
compile: compile,
|
compile: compile,
|
||||||
execute: execute,
|
execute: execute,
|
||||||
load: load,
|
load: load,
|
||||||
parse: parse,
|
parse: parse
|
||||||
sourceMapSupport: {
|
|
||||||
retrieveSourceMap: function(source) {
|
|
||||||
var map = sourceMaps[source];
|
|
||||||
return map ? { url: source, map: map } : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
// Pass on `this` as the binding object, so we can reference Acorn both in
|
// Pass on `this` as the binding object, so we can reference Acorn both in
|
||||||
// development and in the built library.
|
// development and in the built library.
|
||||||
|
|
25
src/node.js
25
src/node.js
|
@ -74,23 +74,40 @@ DOMParser.prototype.parseFromString = function(string, contenType) {
|
||||||
return div.firstChild;
|
return div.firstChild;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var sourceMaps = {};
|
||||||
|
var sourceMapSupport = {
|
||||||
|
retrieveSourceMap: function(source) {
|
||||||
|
var map = sourceMaps[source];
|
||||||
|
return map ? { url: source, map: map } : null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Register the .pjs extension for automatic compilation as PaperScript
|
// Register the .pjs extension for automatic compilation as PaperScript
|
||||||
require.extensions['.pjs'] = function(module, filename) {
|
require.extensions['.pjs'] = function(module, filename) {
|
||||||
// Requiring a PaperScript on Node.js returns an initialize method which
|
// Requiring a PaperScript on Node.js returns an initialize method which
|
||||||
// needs to receive a Canvas object when called and returns the
|
// needs to receive a Canvas object when called and returns the
|
||||||
// PaperScope.
|
// PaperScope.
|
||||||
module.exports = function(canvas) {
|
module.exports = function(canvas) {
|
||||||
var source = fs.readFileSync(filename, 'utf8');
|
// TODO: Fix this once we can require('paper') from node specific code.
|
||||||
|
paper.PaperScript.sourceMapSupport = sourceMapSupport;
|
||||||
|
var source = fs.readFileSync(filename, 'utf8'),
|
||||||
|
code = 'require("source-map-support").install(paper.PaperScript.sourceMapSupport);\n' + source,
|
||||||
|
compiled = paper.PaperScript.compile(code, {
|
||||||
|
url: filename,
|
||||||
|
source: source,
|
||||||
|
sourceMaps: true,
|
||||||
|
offset: -1 // remove require("source-map-support")...
|
||||||
|
}),
|
||||||
scope = new paper.PaperScope();
|
scope = new paper.PaperScope();
|
||||||
|
// Keep track of sourceMaps so retrieveSourceMap() can link them up
|
||||||
scope.setup(canvas);
|
scope.setup(canvas);
|
||||||
scope.__filename = filename;
|
scope.__filename = filename;
|
||||||
scope.__dirname = path.dirname(filename);
|
scope.__dirname = path.dirname(filename);
|
||||||
// Expose core methods and values
|
// Expose core methods and values
|
||||||
scope.require = require;
|
scope.require = require;
|
||||||
scope.console = console;
|
scope.console = console;
|
||||||
paper.PaperScript.execute(source, scope, {
|
sourceMaps[filename] = compiled.map;
|
||||||
url: filename
|
paper.PaperScript.execute(compiled, scope);
|
||||||
});
|
|
||||||
return scope;
|
return scope;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue