Merge remote-tracking branch 'cappuccino/master' into plainsliderfix

This commit is contained in:
daboe01
2017-09-14 09:10:56 +02:00
20 changed files with 861 additions and 264 deletions
+5 -1
View File
@@ -66,6 +66,10 @@ if (typeof OBJJ_COMPILER_FLAGS !== 'undefined')
case "InlineMsgSend":
flags.inlineMsgSendFunctions = true;
break;
case "SourceMap":
flags.sourceMap = true;
break;
}
}
FileExecutable.setCurrentCompilerFlags(flags);
@@ -180,4 +184,4 @@ GLOBAL(objj_import) = function()
{
CPLog.warn("objj_import is deprecated, use objj_importFile instead");
objj_importFile.apply(this, arguments);
}
};
+1 -1
View File
@@ -914,4 +914,4 @@ GLOBAL(CFCopyLocalizedStringWithDefaultValue) = function (key, tableName, bundle
GLOBAL(CFBundleGetMainBundle) = function ()
{
return CFBundle.mainBundle();
}
};
-36
View File
@@ -366,42 +366,6 @@ function FileRequest(/*CFURL*/ aURL, onsuccess, onfailure, onprogress)
if (aURL.pathExtension() === "plist")
request.overrideMimeType("text/xml");
#if COMMONJS
if (aURL.pathExtension().toLowerCase() === "j")
{
var aFilePath = aURL.toString().substring(5),
OS = require("os"),
gccFlags = require("objective-j").FileExecutable.currentGccCompilerFlags(),
chunk,
fileContents = "";
try
{
var gcc = OS.popen("gcc -E -x c -P " + (gccFlags ? gccFlags : "") + " " + OS.enquote(aFilePath), { charset:"UTF-8" });
while (chunk = gcc.stdout.read())
fileContents += chunk;
}
finally
{
gcc.stdin.close();
gcc.stdout.close();
gcc.stderr.close();
}
if (fileContents.length > 0)
{
request._nativeRequest.responseText = fileContents;
onsuccess({request: request});
}
else
{
onfailure({request: request});
}
return;
}
#endif
var loaded = 0,
progressHandler = null;
+2 -2
View File
@@ -597,7 +597,7 @@ CFPropertyList.propertyListFromXML = function(/*String | XMLNode*/ aStringOrXMLN
object = decodeHTMLComponent(FIRST_CHILD(XMLNode) ? TEXT_CONTENT(XMLNode) : "");
break;
case PLIST_DATE: var timestamp = Date.parseISO8601(TEXT_CONTENT(XMLNode));
object = isNaN(timestamp) ? new Date() : new Date(timestamp);
break;
@@ -667,4 +667,4 @@ GLOBAL(CPPropertyListCreateFromData) = function(/*CFData*/ data, /*Format*/ aFor
GLOBAL(CPPropertyListCreateData) = function(/*PropertyList*/ aPropertyList, /*Format*/ aFormat)
{
return CFPropertyList.dataFromPropertyList(aPropertyList, aFormat);
}
};
+30 -1
View File
@@ -91,7 +91,7 @@ exports.run = function(args)
if (argv[0] === "--help" || argv[0] === "-h")
{
print("Usage (objj): " + args[0] + " [options] [--] files...");
print("Usage (objj): " + args[0].split("/").pop() + " [options] [--] files...");
print(" -v, --version print the current version of objj");
print(" -I, --objj-include-paths include a specific framework paths")
print(" -h, --help print this help");
@@ -150,6 +150,35 @@ exports.run = function(args)
flags.inlineMsgSendFunctions = true;
ObjectiveJ.FileExecutable.setCurrentCompilerFlags(flags);
break;
case "-g":
case "--include-debug-symbols":
argv.shift();
var flags = ObjectiveJ.FileExecutable.currentCompilerFlags();
flags.includeMethodFunctionNames = true;
ObjectiveJ.FileExecutable.setCurrentCompilerFlags(flags);
break;
case "-T":
case "--dont-include-type-signatures":
argv.shift();
var flags = ObjectiveJ.FileExecutable.currentCompilerFlags();
flags.includeIvarTypeSignatures = true;
flags.includeMethodArgumentTypeSignatures = true;
ObjectiveJ.FileExecutable.setCurrentCompilerFlags(flags);
break;
case "-O2":
case "--inline-msg-send":
argv.shift();
var flags = ObjectiveJ.FileExecutable.currentCompilerFlags();
flags.inlineMsgSendFunctions = true;
ObjectiveJ.FileExecutable.setCurrentCompilerFlags(flags);
break;
default:
print(args[0].split("/").pop() + " illegal option " + argv[0]);
OS.exit(1);
}
}
}
@@ -2,22 +2,21 @@
function ObjectiveJLoader() {
var loader = {};
var factories = {};
loader.reload = function(topId, path) {
if (!global.ObjectiveJ)
if (!global.ObjectiveJ)
global.ObjectiveJ = require("objective-j");
//print("loading objective-j: " + topId + " (" + path + ")");
factories[topId] = ObjectiveJ.make_narwhal_factory(path);
factories[topId].path = path;
}
loader.load = function(topId, path) {
if (!factories.hasOwnProperty(topId))
loader.reload(topId, path);
return factories[topId];
}
return loader;
};
+1 -1
View File
@@ -275,4 +275,4 @@ GLOBAL(objj_debug_typecheck) = function(expectedType, object)
actualType = typeof object;
throw ("expected=" + expectedType + ", actual=" + actualType);
}
};
+1 -1
View File
@@ -81,4 +81,4 @@ EventDispatcher.prototype.dispatchEvent = function(/*Event*/ anEvent)
if (manual)
manual(anEvent);
}
};
+167 -10
View File
@@ -21,9 +21,10 @@
*/
var ExecutableUnloadedFileDependencies = 0,
ExecutableLoadingFileDependencies = 1,
ExecutableLoadedFileDependencies = 2,
var ExecutableUnloadedFileDependencies = 0,
ExecutableLoadingFileDependencies = 1,
ExecutableLoadedFileDependencies = 2,
ExecutableCantStartLoadYetFileDependencies = 3,
AnonymousExecutableCount = 0;
function Executable(/*String*/ aCode, /*Array*/ fileDependencies, /*CFURL|String*/ aURL, /*Function*/ aFunction, /*ObjJCompiler*/aCompiler, /*Dictionary*/ aFilenameTranslateDictionary)
@@ -40,13 +41,21 @@ function Executable(/*String*/ aCode, /*Array*/ fileDependencies, /*CFURL|String
this._fileDependencies = fileDependencies;
this._filenameTranslateDictionary = aFilenameTranslateDictionary;
if (fileDependencies.length)
// This is a little hacky but if fileDependencies is null we can start loading file dependencies yet
if (!fileDependencies)
{
this._fileDependencyStatus = ExecutableCantStartLoadYetFileDependencies;
this._fileDependencyCallbacks = [];
}
else if (fileDependencies.length)
{
this._fileDependencyStatus = ExecutableUnloadedFileDependencies;
this._fileDependencyCallbacks = [];
}
else
{
this._fileDependencyStatus = ExecutableLoadedFileDependencies;
}
if (this._function)
return;
@@ -168,7 +177,7 @@ Executable.prototype.execute = function()
}
this._compiler.popImport();
this.setCode(this._compiler.compilePass2());
this.setCode(this._compiler.compilePass2(), this._compiler.map());
if (FileExecutable.printWarningsAndErrors(this._compiler, exports.messageOutputFormatInXML))
throw "Compilation error";
@@ -197,7 +206,7 @@ Executable.prototype.code = function()
DISPLAY_NAME(Executable.prototype.code);
Executable.prototype.setCode = function(code)
Executable.prototype.setCode = function(code, sourceMap)
{
this._code = code;
@@ -219,7 +228,24 @@ Executable.prototype.setCode = function(code)
//if (YES) {
var absoluteString = this.URL().absoluteString();
code += "/**/\n//# sourceURL=" + absoluteString;
code += "/**/\n//# sourceURL=" + absoluteString + "s";
if (sourceMap)
{
// The new Function constructor will add a function header before the first line
// The compiler adds a new line as the first character to the code to get the spurce
// mapping correct. We have to remove it here
code = code.substring(2);
var sourceMapBase64;
if (typeof btoa === 'function')
sourceMapBase64 = btoa(UTF16ToUTF8(sourceMap));
else if (typeof Buffer === 'function')
sourceMapBase64 = new Buffer(sourceMap).toString("base64");
if (sourceMapBase64)
code += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + sourceMapBase64;
}
//} else {
// // Firebug only does it for "eval()", not "new Function()". Ugh. Slower.
// var functionText = "(function(){"+GET_CODE(aFragment)+"/**/\n})\n//# sourceURL="+GET_FILE(aFragment).path;
@@ -244,6 +270,13 @@ Executable.prototype.fileDependencies = function()
DISPLAY_NAME(Executable.prototype.fileDependencies);
Executable.prototype.setFileDependencies = function(newValue)
{
this._fileDependencies = newValue;
}
DISPLAY_NAME(Executable.prototype.setFileDependencies);
Executable.prototype.hasLoadedFileDependencies = function()
{
return this._fileDependencyStatus === ExecutableLoadedFileDependencies;
@@ -278,6 +311,21 @@ Executable.prototype.loadFileDependencies = function(aCallback)
DISPLAY_NAME(Executable.prototype.loadFileDependencies);
Executable.prototype.setExecutableUnloadedFileDependencies = function()
{
if (this._fileDependencyStatus === ExecutableCantStartLoadYetFileDependencies)
this._fileDependencyStatus = ExecutableUnloadedFileDependencies;
}
DISPLAY_NAME(Executable.prototype.setExecutableUnloadedFileDependencies);
Executable.prototype.isExecutableCantStartLoadYetFileDependencies = function()
{
return this._fileDependencyStatus === ExecutableCantStartLoadYetFileDependencies;
}
DISPLAY_NAME(Executable.prototype.setExecutableUnloadedFileDependencies);
function loadFileDependenciesForExecutable(/*Executable*/ anExecutable)
{
fileDependencyExecutables.push(anExecutable);
@@ -351,6 +399,7 @@ function fileExecutableDependencyLoadFinished()
Executable.prototype.referenceURL = function()
{
if (this._referenceURL === undefined)
// Removed the filename (if any) from the path to get the directory
this._referenceURL = new CFURL(".", this.URL());
return this._referenceURL;
@@ -473,11 +522,12 @@ Executable.resetCachedFileExecutableSearchers = function()
Executable.fileExecutableSearcherForURL = function(/*CFURL*/ referenceURL)
{
var referenceURLString = referenceURL.absoluteString(),
cachedFileExecutableSearcher = cachedFileExecutableSearchers[referenceURLString],
aFilenameTranslateDictionary = Executable.filenameTranslateDictionary ? Executable.filenameTranslateDictionary() : null;
cachedFileExecutableSearcher = cachedFileExecutableSearchers[referenceURLString];
if (!cachedFileExecutableSearcher)
{
var aFilenameTranslateDictionary = Executable.filenameTranslateDictionary ? Executable.filenameTranslateDictionary() : null;
cachedFileExecutableSearcher = function(/*CFURL*/ aURL, /*BOOL*/ isQuoted, /*Function*/ success)
{
var cacheUID = (isQuoted && referenceURL || "") + aURL,
@@ -503,7 +553,7 @@ Executable.fileExecutableSearcherForURL = function(/*CFURL*/ referenceURL)
if (!aStaticResource)
{
var compilingFileUrl = exports.ObjJCompiler ? exports.ObjJCompiler.currentCompileFile : null;
throw new Error("Could not load file at " + aURL + (compilingFileUrl ? " when compiling " + compilingFileUrl : ""));
throw new Error("Could not load file at " + aURL + (compilingFileUrl ? " when compiling " + compilingFileUrl : "") + "\nwith includeURLs: " + StaticResource.includeURLs());
}
cachedFileExecutableSearchResults[cacheUID] = aStaticResource;
@@ -519,3 +569,110 @@ Executable.fileExecutableSearcherForURL = function(/*CFURL*/ referenceURL)
}
DISPLAY_NAME(Executable.fileExecutableSearcherForURL);
/*
* Adaption to javascript by Malte Tancred 2012 from ConvertUTF.[ch] by Unicode, Inc.
* Speed improvements by Martin Carlberg 2016
*
* Original copyright follows.
*/
/*
* Copyright 2001-2004 Unicode, Inc.
*
* Disclaimer
*
* This source code is provided as is by Unicode, Inc. No claims are
* made as to fitness for any particular purpose. No warranties of any
* kind are expressed or implied. The recipient agrees to determine
* applicability of information provided. If this file has been
* purchased on magnetic or optical media from Unicode, Inc., the
* sole remedy for any claim will be exchange of defective media
* within 90 days of receipt.
*
* Limitations on Rights to Redistribute This Code
*
* Unicode, Inc. hereby grants the right to freely use the information
* supplied in this file in the creation of products supporting the
* Unicode Standard, and to make copies of this file in any form
* for internal or external distribution as long as this notice
* remains attached.
*/
/* ---------------------------------------------------------------------
Conversions between UTF32, UTF-16, and UTF-8. Source code file.
Author: Mark E. Davis, 1994.
Rev History: Rick McGowan, fixes & updates May 2001.
Sept 2001: fixed const & error conditions per
mods suggested by S. Parent & A. Lillich.
June 2002: Tim Dodd added detection and handling of incomplete
source sequences, enhanced error detection, added casts
to eliminate compiler warnings.
July 2003: slight mods to back out aggressive FFFE detection.
Jan 2004: updated switches in from-UTF8 conversions.
Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
See the header file "ConvertUTF.h" for complete documentation.
------------------------------------------------------------------------ */
var SURROGATE_HIGH_START = 0xD800;
var SURROGATE_HIGH_END = 0xDBFF;
var SURROGATE_LOW_START = 0xDC00;
var SURROGATE_LOW_END = 0xDFFF;
var REPLACEMENT_CHAR = 0xFFFD;
var FIRSTBYTEMARK = [0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC];
function UTF16ToUTF8(source) {
var target = "";
var currentPos = 0;
for (var i = 0; i < source.length; i++) {
var c = source.charCodeAt(i);
if (c < 0x80) continue;
if (i > currentPos)
target += source.substring(currentPos, i);
if (c >= SURROGATE_HIGH_START && c <= SURROGATE_HIGH_END) {
i++;
if (i < source.length) {
var c2 = source.charCodeAt(i);
if (c2 >= SURROGATE_LOW_START && c2 <= SURROGATE_LOW_END) {
c = ((c - SURROGATE_HIGH_START) << 10) + (c2 - SURROGATE_LOW_START) + 0x10000;
} else {
// illegal second surrogate char
return null;
}
} else {
// missing second surrogate in pair
return null;
}
} else if (c >= SURROGATE_LOW_START && c <= SURROGATE_LOW_END) {
// stray surrogate
return null;
}
currentPos = i + 1;
enc = [];
var cc = c;
if (cc >= 0x110000) { cc = 0x800; c = REPLACEMENT_CHAR; }
if (cc >= 0x10000) { enc.unshift(String.fromCharCode((c | 0x80) & 0xBF)); c >>= 6; }
if (cc >= 0x800) { enc.unshift(String.fromCharCode((c | 0x80) & 0xBF)); c >>= 6; }
if (cc >= 0x80) { enc.unshift(String.fromCharCode((c | 0x80) & 0xBF)); c >>= 6; }
enc.unshift(String.fromCharCode( c | FIRSTBYTEMARK[enc.length]));
target += enc.join("");
}
if (currentPos === 0) return source;
if (i > currentPos)
target += source.substring(currentPos, i);
return target;
}
DISPLAY_NAME(UTF16ToUTF8);
+1 -1
View File
@@ -49,4 +49,4 @@ FileDependency.prototype.toMarkedString = function()
FileDependency.prototype.toString = function()
{
return (this.isLocal() ? "LOCAL: " : "STD: ") + this.URL();
}
};
+144 -34
View File
@@ -41,11 +41,138 @@ function FileExecutable(/*CFURL|String*/ aURL, /*Dictionary*/ aFilenameTranslate
executable = NULL,
extension = aURL.pathExtension().toLowerCase();
this._hasExecuted = NO;
if (fileContents.match(/^@STATIC;/))
executable = decompile(fileContents, aURL);
else if ((extension === "j" || !extension) && !fileContents.match(/^{/))
{
var compiler = exports.ObjJCompiler.compileFileDependencies(fileContents, aURL, currentCompilerFlags || {});
var compilerOptions = currentCompilerFlags || {};
this.cachedIncludeFileSearchResultsContent = {};
this.cachedIncludeFileSearchResultsURL = {};
compile(this, fileContents, aURL, compilerOptions, aFilenameTranslateDictionary);
return;
}
else
executable = new Executable(fileContents, [], aURL);
Executable.apply(this, [executable.code(), executable.fileDependencies(), aURL, executable._function, executable._compiler, aFilenameTranslateDictionary]);
}
exports.FileExecutable = FileExecutable;
FileExecutable.prototype = new Executable();
var compile = function(self, fileContents, aURL, compilerOptions, aFilenameTranslateDictionary)
{
var acornOptions = compilerOptions.acornOptions || (compilerOptions.acornOptions = {});
acornOptions.preprocessGetIncludeFile = function(filePath, isQuoted) {
var referenceURL = new CFURL(".", aURL), // Remove the filename from the url
includeURL = new CFURL(filePath);
var cacheUID = (isQuoted && referenceURL || "") + includeURL,
cachedResult = self.cachedIncludeFileSearchResultsContent[cacheUID];
if (!cachedResult) {
var isAbsoluteURL = (includeURL instanceof CFURL) && includeURL.scheme(),
compileWhenCompleted = NO;
function completed(/*StaticResource*/ aStaticResource) {
var includeString = aStaticResource && aStaticResource.contents(),
lastCharacter = includeString && includeString.charCodeAt(includeString.length - 1);
if (includeString == null) throw new Error("Can't load file " + includeURL);
// Add a new line if the last character is not. If the last thing is a '#define' of other preprocess
// token it will not be handled correctly if we don't have a end of line at the end.
if (lastCharacter !== 10 && lastCharacter !== 13 && lastCharacter !== 8232 && lastCharacter !== 8233) {
includeString += '\n';
}
self.cachedIncludeFileSearchResultsContent[cacheUID] = includeString;
self.cachedIncludeFileSearchResultsURL[cacheUID] = aStaticResource.URL();
if (compileWhenCompleted)
compile(self, fileContents, aURL, compilerOptions, aFilenameTranslateDictionary);
}
if (isQuoted || isAbsoluteURL)
{
if (!isAbsoluteURL)
includeURL = new CFURL(includeURL, new CFURL((aFilenameTranslateDictionary[aURL.lastPathComponent()] || "."), referenceURL));
StaticResource.resolveResourceAtURL(includeURL, NO, completed);
}
else
StaticResource.resolveResourceAtURLSearchingIncludeURLs(includeURL, completed);
// Now we try to get the cached result again. If we get it then the completed function has already
// executed and we can return the include dictionary.
cachedResult = self.cachedIncludeFileSearchResultsContent[cacheUID];
}
if (cachedResult) {
return {include: cachedResult, sourceFile: self.cachedIncludeFileSearchResultsURL[cacheUID]};
} else {
// When the file is not available (resolved) return null to tell the parser to throw an exception to exit
// Also tell the completed function to compile when finished.
compileWhenCompleted = YES
return null;
}
};
var includeFiles = currentCompilerFlags && currentCompilerFlags.includeFiles,
allPreIncludesResolved = true;
acornOptions.preIncludeFiles = [];
if (includeFiles) for (var i = 0, size = includeFiles.length; i < size; i++)
{
var includeFileUrl = makeAbsoluteURL(includeFiles[i]);
try
{
// try to get all pre include files that acorn will parse before the file from 'aURL'
var aResource = StaticResource.resourceAtURL(makeAbsoluteURL(includeFileUrl));
}
catch (e)
{
// Ok, the file is not available (resolved). Resolve all of the files and try again when available.
StaticResource.resolveResourcesAtURLs(includeFiles.map(function(u) {return makeAbsoluteURL(u)}), function() {
compile(self, fileContents, aURL, compilerOptions, aFilenameTranslateDictionary);
});
allPreIncludesResolved = false;
break;
}
if (aResource)
{
if (aResource.isNotFound()) {
throw new Error("--include file not found " + includeUrl);
}
var includeString = aResource.contents();
var lastCharacter = includeString.charCodeAt(includeString.length - 1);
// Add a new line if the last character is not. If the last thing is a '#define' of other preprocess
// token it will not be handled correctly if we don't have a end of line at the end.
if (lastCharacter !== 10 && lastCharacter !== 13 && lastCharacter !== 8232 && lastCharacter !== 8233)
includeString += '\n';
acornOptions.preIncludeFiles.push({include: includeString, sourceFile: includeFileUrl.toString()});
}
}
if (allPreIncludesResolved)
{
var compiler = exports.ObjJCompiler.compileFileDependencies(fileContents, aURL, compilerOptions);
var warningsAndErrors = compiler.warningsAndErrors;
// Kind of a hack but if we get a file not found error on a #include the get include function above should have asked for the resource
// so we should be able to just bail out and wait for the the next call to compile when the include file is loaded (resolved)
if (warningsAndErrors && warningsAndErrors.length === 1 && warningsAndErrors[0].message.indexOf("file not found") > -1)
return;
if (FileExecutable.printWarningsAndErrors(compiler, exports.messageOutputFormatInXML))
throw "Compilation error";
@@ -53,19 +180,25 @@ function FileExecutable(/*CFURL|String*/ aURL, /*Dictionary*/ aFilenameTranslate
var fileDependencies = compiler.dependencies.map(function (aFileDep) {
return new FileDependency(new CFURL(aFileDep.url), aFileDep.isLocal);
});
executable = new Executable(compiler.jsBuffer ? compiler.jsBuffer.toString() : null, fileDependencies, compiler.URL, null, compiler);
}
else
executable = new Executable(fileContents, [], aURL);
Executable.apply(this, [executable.code(), executable.fileDependencies(), aURL, executable._function, executable._compiler, aFilenameTranslateDictionary]);
this._hasExecuted = NO;
if (self.isExecutableCantStartLoadYetFileDependencies())
{
// Include files that was not loaded has cancelled the compiler so we are already an initialized Executable.
// Just set the status so we can start loading the file dependencies.
self.setFileDependencies(fileDependencies);
self.setExecutableUnloadedFileDependencies();
self.loadFileDependencies();
}
else if (self._fileDependencyStatus == null)
{
// Are we still a FileExecutable. Call 'super' init method to make us a initilized subclass of an Executable.
executable = new Executable(compiler && compiler.jsBuffer ? compiler.jsBuffer.toString() : null, fileDependencies, aURL, null, compiler);
Executable.apply(self, [executable.code(), executable.fileDependencies(), aURL, executable._function, executable._compiler, aFilenameTranslateDictionary]);
}
}
exports.FileExecutable = FileExecutable;
FileExecutable.prototype = new Executable();
DISPLAY_NAME(compile);
#ifdef COMMONJS
FileExecutable.allFileExecutables = function()
@@ -159,30 +292,7 @@ FileExecutable.setCurrentGccCompilerFlags = function(/*String*/ compilerFlags)
currentGccCompilerFlags = compilerFlags;
var args = compilerFlags.split(" "),
count = args.length,
objjcFlags = {};
for (var index = 0; index < count; ++index)
{
var argument = args[index];
if (argument.indexOf("-g") === 0)
objjcFlags.includeMethodFunctionNames = true;
else if (argument.indexOf("-O") === 0) {
objjcFlags.inlineMsgSendFunctions = true;
// FIXME: currently we are sending in '-O2' when we want InlineMsgSend. Here we only check if it is '-O...'.
// Maybe we should have some other option for this
if (argument.length > 2)
objjcFlags.inlineMsgSendFunctions = true;
}
//else if (argument.indexOf("-G") === 0)
//objjcFlags |= ObjJAcornCompiler.Flags.Generate;
else if (argument.indexOf("-T") === 0) {
objjcFlags.includeIvarTypeSignatures = false;
objjcFlags.includeMethodArgumentTypeSignatures = false;
}
}
var objjcFlags = exports.ObjJCompiler.parseGccCompilerFlags(compilerFlags);
FileExecutable.setCurrentCompilerFlags(objjcFlags);
}
+34 -12
View File
@@ -26,6 +26,13 @@ var FILE = require("file"),
OS = require("os"),
stream = require("narwhal/term").stream;
var walk = require("./acornwalk").acorn.walk;
acorn = {walk: walk};
acorn = require("./acorn").acorn;
var compiler = require("./ObjJAcornCompiler").ObjJCompiler;
//$BUILD_CONFIGURATION_DIR = "../Build"
$BROWSER_FILE = FILE.join("Browser", "Objective-J.js");
@@ -106,7 +113,7 @@ function environmentFlags()
return environments.map(function(anEnvironment) {
return "-D" + anEnvironment.toUpperCase();
}).concat("-DENVIRONMENTS=" + OS.enquote(JSON.stringify(environments)));
}).concat("-DENVIRONMENTS=" + JSON.stringify(environments));
}
var SHRINKSAFE = require("minify/shrinksafe");
@@ -114,26 +121,41 @@ function compressor(code) {
return SHRINKSAFE.compress(code, { charset : "UTF-8", useServer : true });
}
var headerText = FILE.read("header.txt", { charset : "UTF-8" });
function gcc(inputFilePath, outputFilePath, flags, compress)
{
stream.print("Building... \0green(" + outputFilePath +"\0)");
// GCC preprocess the file.
var cmd = ["gcc", "-E", "-x", "c", "-P"].concat(flags, inputFilePath).join(" "),
contents = FILE.read("header.txt", { charset : "UTF-8" });
var source = FILE.read(inputFilePath, { charset : "UTF-8" });
var compilerOptions = compiler.parseGccCompilerFlags(flags.join(" "));
var acornOptions = compilerOptions.acornOptions || (compilerOptions.acornOptions = {});
try
{
var gcc = OS.popen(cmd, { charset:"UTF-8" });
contents += gcc.stdout.read();
acornOptions.preprocessGetIncludeFile = function(filePath, isQuoted) {
var includeContent = FILE.read(filePath, { charset : "UTF-8" });
//print ("Include content for file '" + filePath + "': " + includeContent);
//print ("Include file '" + filePath + "'");
return {include: includeContent, sourceFile: filePath};
}
finally
var c = compiler.compile(source, inputFilePath, compilerOptions);
var warnings = [],
anyErrors = false;
for (var i = 0; i < c.warningsAndErrors.length; i++)
{
gcc.stdin.close();
gcc.stdout.close();
gcc.stderr.close();
var warning = c.warningsAndErrors[i],
message = c.prettifyMessage(warning);
// Set anyErrors to 'true' if there are any errors in the list
anyErrors = anyErrors || warning.messageType === "ERROR";
print(message);
}
if (anyErrors) throw "Compilation Error";
var code = c.code();
var contents = headerText + code;
if (FILE.extension(inputFilePath) === ".js" && compress)
contents = compressor(contents);
+197 -82
View File
@@ -16,14 +16,12 @@
(function(mod)
{
//print("Compiler INIT! exports: " + typeof exports + ", module: " + typeof module + ", define: " + typeof define);
mod(exports.ObjJCompiler || (exports.ObjJCompiler = {}), exports.acorn, exports.acorn.walk/*, sourceMap*/); // Plain browser env
mod(exports.ObjJCompiler || (exports.ObjJCompiler = {}), exports.acorn || acorn, (exports.acorn || acorn).walk, typeof sourceMap != "undefined" ? sourceMap : null); // Plain browser env
})(function(exports, acorn, walk, sourceMap)
{
"use strict";
exports.version = "0.3.7";
//exports.acorn = acorn;
var Scope = function(prev, base)
{
@@ -280,7 +278,7 @@ GlobalVariableMaybeWarning.prototype.isEqualTo = function(/* GlobalVariableMaybe
return true;
}
function StringBuffer(useSourceNode, file)
function StringBuffer(useSourceNode, file, sourceContent)
{
if (useSourceNode) {
this.rootNode = new sourceMap.SourceNode();
@@ -289,8 +287,21 @@ function StringBuffer(useSourceNode, file)
this.isEmpty = this.isEmptySourceNode;
this.appendStringBuffer = this.appendStringBufferSourceNode;
this.length = this.lengthSourceNode;
if (file)
this.file = file.toString();
if (file) {
var fileString = file.toString(),
filename = fileString.substr(fileString.lastIndexOf('/') + 1),
sourceRoot = fileString.substr(0, fileString.lastIndexOf('/') + 1);
this.filename = filename;
if (sourceRoot.length > 0)
this.sourceRoot = sourceRoot;
if (sourceContent != null)
this.rootNode.setSourceContent(filename, sourceContent);
}
if (sourceContent != null)
this.sourceContent = sourceContent;
} else {
this.atoms = [];
this.concat = this.concatString;
@@ -308,7 +319,7 @@ StringBuffer.prototype.toStringString = function()
StringBuffer.prototype.toStringSourceNode = function()
{
return this.rootNode.toStringWithSourceMap({file: this.file});
return this.rootNode.toStringWithSourceMap({file: this.filename + "s", sourceRoot:this.sourceRoot});
}
StringBuffer.prototype.concatString = function(aString)
@@ -316,11 +327,11 @@ StringBuffer.prototype.concatString = function(aString)
this.atoms.push(aString);
}
StringBuffer.prototype.concatSourceNode = function(aString, node)
StringBuffer.prototype.concatSourceNode = function(aString, node, originalName)
{
if (node) {
//console.log("Snippet: " + aString + ", line: " + node.loc.start.line + ", column: " + node.loc.start.column + ", source: " + node.loc.source);
this.rootNode.add(new sourceMap.SourceNode(node.loc.start.line, node.loc.start.column, node.loc.source, aString));
this.rootNode.add(new sourceMap.SourceNode(node.loc.start.line, node.loc.start.column, node.loc.source, aString, originalName));
} else
this.rootNode.add(aString);
if (!this.notEmpty)
@@ -624,10 +635,13 @@ var isInInstanceof = acorn.makePredicate("in instanceof");
// Turn on `sourceMap` generate a source map for the compiler file.
sourceMap: false,
// Turn on `sourceMapIncludeSource` will include the source code in the source map.
sourceMapIncludeSource: false,
// The compiler can do different passes.
// 1: Parse and walk AST tree to collect file dependencies.
// 2: Parse and walk to generate code.
// Pass one is only for when the Objective-J load and runtime.
// Pass one is only for the Objective-J load and runtime.
pass: 2,
// Pass in class definitions. New class definitions in source file will be added here when compiling.
@@ -678,6 +692,12 @@ var isInInstanceof = acorn.makePredicate("in instanceof");
// Turn off `inlineMsgSendFunctions` to use message send functions. Needed to use message send decorators.
inlineMsgSendFunctions: true,
// An array of macro objects and/or text definitions may be passed in.
// Definitions may be in one of two forms:
// macro
// macro=body
macros: null,
};
// We copy the options to a new object as we don't want to mess up incoming options when we start compiling.
@@ -710,7 +730,7 @@ var ObjJAcornCompiler = function(/*String*/ aString, /*CFURL*/ aURL, options)
this.formatDescription = options.formatDescription;
this.includeComments = options.includeComments;
this.transformNamedFunctionDeclarationToAssignment = options.transformNamedFunctionDeclarationToAssignment;
this.jsBuffer = new StringBuffer(this.createSourceMap, aURL);
this.jsBuffer = new StringBuffer(this.createSourceMap, aURL, options.sourceMap && options.sourceMapIncludeSource ? this.source : null);
this.imBuffer = null;
this.cmBuffer = null;
this.dependencies = [];
@@ -727,7 +747,7 @@ var ObjJAcornCompiler = function(/*String*/ aString, /*CFURL*/ aURL, options)
if (acornOptions)
{
if (!acornOptions.sourceFile && this.URL)
if (this.URL)
acornOptions.sourceFile = this.URL.substr(this.URL.lastIndexOf('/') + 1);
if (options.sourceMap && !acornOptions.locations)
acornOptions.locations = true;
@@ -739,6 +759,14 @@ var ObjJAcornCompiler = function(/*String*/ aString, /*CFURL*/ aURL, options)
acornOptions.locations = true;
}
if (options.macros)
{
if (acornOptions.macros)
acornOptions.macros.concat(options.macros);
else
acornOptions.macros = options.macros;
}
try {
this.tokens = acorn.parse(aString, options.acornOptions);
(this.pass === 2 && (options.includeComments || options.formatDescription) ? compileWithFormat : compile)(this.tokens, new Scope(null ,{ compiler: this }), this.pass === 2 ? pass2 : pass1);
@@ -795,14 +823,16 @@ exports.compileFileDependencies = function(/*String*/ aString, /*CFURL*/ aURL, o
ObjJAcornCompiler.prototype.compilePass2 = function()
{
var options = this.options;
exports.currentCompileFile = this.URL;
this.pass = this.options.pass = 2;
this.jsBuffer = new StringBuffer(this.createSourceMap, this.URL);
this.pass = options.pass = 2;
this.jsBuffer = new StringBuffer(this.createSourceMap, this.URL, options.sourceMap && options.sourceMapIncludeSource ? this.source : null);
// To get the source mapping correct when the new Function construtor is used we add a
// new line as first thing in the code.
if (this.createSourceMap)
this.jsBuffer.concat("\n");
this.jsBuffer.concat("\n\n");
this.warningsAndErrors = [];
try {
@@ -959,6 +989,76 @@ ObjJAcornCompiler.prototype.getTypeDef = function(/* String */ aTypeDefName)
return null;
}
/*!
Return a parsed option dictionary
*/
exports.parseGccCompilerFlags = function(/* String */ compilerFlags)
{
var args = (compilerFlags || "").split(" "),
count = args.length,
objjcFlags = {};
for (var index = 0; index < count; ++index)
{
var argument = args[index];
if (argument.indexOf("-g") === 0)
objjcFlags.includeMethodFunctionNames = true;
else if (argument.indexOf("-O") === 0) {
objjcFlags.inlineMsgSendFunctions = true;
// FIXME: currently we are sending in '-O2' when we want InlineMsgSend. Here we only check if it is '-O...'.
// Maybe we should have some other option for this
if (argument.length > 2)
objjcFlags.inlineMsgSendFunctions = true;
}
//else if (argument.indexOf("-G") === 0)
//objjcFlags |= ObjJAcornCompiler.Flags.Generate;
else if (argument.indexOf("-T") === 0) {
objjcFlags.includeIvarTypeSignatures = false;
objjcFlags.includeMethodArgumentTypeSignatures = false;
}
else if (argument.indexOf("-S") === 0) {
objjcFlags.sourceMap = true;
objjcFlags.sourceMapIncludeSource = true;
}
else if (argument.indexOf("--include") === 0) {
var includeUrl = args[++index],
firstChar = includeUrl && includeUrl.charCodeAt(0);
// Poor mans unquote
if (firstChar === 34 || firstChar === 39) // '"', "'"
includeUrl = includeUrl.substring(1, includeUrl.length - 1);
(objjcFlags.includeFiles || (objjcFlags.includeFiles = [])).push(includeUrl);
}
/* else if (argument.indexOf("-I") === 0) {
var includeUrl = argument.substring(2),
firstChar = includeUrl && includeUrl.charCodeAt(0);
(objjcFlags.includeFiles || (objjcFlags.includeFiles = [])).push(includeUrl);
}
else if (argument.indexOf("'-I") === 0) {
var includeUrl = argument.substring(3, argument.length - 1),
firstChar = includeUrl && includeUrl.charCodeAt(0);
(objjcFlags.includeFiles || (objjcFlags.includeFiles = [])).push(includeUrl);
}
else if (argument.indexOf('"-I') === 0) {
var includeUrl = argument.substring(3, argument.length - 1),
firstChar = includeUrl && includeUrl.charCodeAt(0);
(objjcFlags.includeFiles || (objjcFlags.includeFiles = [])).push(includeUrl);
}*/
else if (argument.indexOf("-D") === 0) {
var macroDefinition = argument.substring(2);
(objjcFlags.macros || (objjcFlags.macros = [])).push(macroDefinition);
}
}
return objjcFlags;
}
ObjJAcornCompiler.methodDefsFromMethodList = function(/* Array */ methodList)
{
var methodSize = methodList.length,
@@ -1006,10 +1106,10 @@ ObjJAcornCompiler.prototype.map = function()
ObjJAcornCompiler.prototype.prettifyMessage = function(/* Message */ aMessage)
{
var line = aMessage.messageForLine,
message = "\n" + line;
message = "\n" + (line || "");
message += (new Array(aMessage.messageOnColumn + 1)).join(" ");
message += (new Array(Math.min(1, line.length) + 1)).join("^") + "\n";
message += (new Array((aMessage.messageOnColumn || 0) + 1)).join(" ");
if (line) message += (new Array(Math.min(1, line.length || 1) + 1)).join("^") + "\n";
message += aMessage.messageType + " line " + aMessage.messageOnLine + " in " + this.URL + ": " + aMessage.message;
return message;
@@ -1309,13 +1409,13 @@ BlockStatement: function(node, st, c, format) {
}
//Simulate a node for the last curly bracket
var endNode = node.loc && { loc: { start: { line : node.loc.end.line, column: node.loc.end.column-1}}, source: node.loc.source};
// var endNode = node.loc && { loc: { start: { line : node.loc.end.line, column: node.loc.end.column}}, source: node.loc.source};
if (format) {
buffer.concatFormat(format.beforeRightBrace);
buffer.concat("}", endNode);
buffer.concat("}", node);
} else {
buffer.concat(indentation.substring(indentationSize));
buffer.concat("}", endNode);
buffer.concat("}", node);
if (!skipIndentation && st.isDecl !== false)
buffer.concat("\n");
st.indentBlockLevel--;
@@ -1351,11 +1451,11 @@ IfStatement: function(node, st, c, format) {
c(node.test, st, "Expression");
if (generate) {
if (format) {
buffer.concat(")");
buffer.concat(")", node);
buffer.concatFormat(format.afterRightParenthesis);
} else {
// We don't want EmptyStatements to generate an extra parenthesis except when it is in a while, for, ...
buffer.concat(node.consequent.type === "EmptyStatement" ? ");\n" : ")\n");
buffer.concat(node.consequent.type === "EmptyStatement" ? ");\n" : ")\n", node);
}
}
indentation += indentStep;
@@ -1367,13 +1467,13 @@ IfStatement: function(node, st, c, format) {
if (generate) {
if (format) {
buffer.concatFormat(format.beforeElse); // Do we need this?
buffer.concat("else");
buffer.concat("else", node);
buffer.concatFormat(format.afterElse);
} else {
var emptyStatement = alternate.type === "EmptyStatement";
buffer.concat(indentation);
// We don't want EmptyStatements to generate an extra parenthesis except when it is in a while, for, ...
buffer.concat(alternateNotIf ? emptyStatement ? "else;\n" : "else\n" : "else ");
buffer.concat(alternateNotIf ? emptyStatement ? "else;\n" : "else\n" : "else ", node);
}
}
if (alternateNotIf)
@@ -1392,10 +1492,10 @@ LabeledStatement: function(node, st, c, format) {
if (!format) buffer.concat(indentation);
c(node.label, st, "IdentifierName");
if (format) {
buffer.concat(":");
buffer.concat(":", node);
buffer.concatFormat(format.afterColon);
} else {
buffer.concat(": ");
buffer.concat(": ", node);
}
}
c(node.body, st, "Statement");
@@ -1456,10 +1556,10 @@ WithStatement: function(node, st, c, format) {
c(node.object, st, "Expression");
if (generate)
if (format) {
buffer.concat(")");
buffer.concat(")", node);
buffer.concatFormat(format.afterRightParenthesis);
} else {
buffer.concat(")\n");
buffer.concat(")\n", node);
}
indentation += indentStep;
c(node.body, st, "Statement");
@@ -1968,7 +2068,7 @@ SequenceExpression: function(node, st, c, format) {
buffer;
if (generate) {
buffer = compiler.jsBuffer;
buffer.concat("(");
buffer.concat("(", node);
}
for (var i = 0; i < node.expressions.length; ++i) {
if (generate && i !== 0)
@@ -2079,7 +2179,7 @@ AssignmentExpression: function(node, st, c, format) {
if (!generate) buffer.concat(compiler.source.substring(compiler.lastPos, node.start));
// Output the dereference function, "(...)(z)"
buffer.concat("(");
buffer.concat("(", node);
// What's being dereferenced could itself be an expression, such as when dereferencing a deref.
if (!generate) compiler.lastPos = node.left.expr.start;
c(node.left.expr, st, "Expression");
@@ -2269,7 +2369,7 @@ Identifier: function(node, st, c) {
st.addMaybeWarning(message);
}
}
if (generate) compiler.jsBuffer.concat(identifier, node);
if (generate) compiler.jsBuffer.concat(identifier, node, "self");
},
// Use this when there should not be a look up to issue warnings or add 'self.' before ivars
IdentifierName: function(node, st, c) {
@@ -2316,7 +2416,7 @@ ArrayLiteral: function(node, st, c) {
buffer.concat("@[");
} else if (!elementLength) {
if (compiler.options.inlineMsgSendFunctions) {
buffer.concat("(___r");
buffer.concat("(___r", node);
buffer.concat(++st.receiverLevel + "");
buffer.concat(" = (CPArray.isa.method_msgSend[\"alloc\"] || _objj_forward)(CPArray, \"alloc\"), ___r");
buffer.concat(st.receiverLevel + "");
@@ -2341,7 +2441,7 @@ ArrayLiteral: function(node, st, c) {
st.maxReceiverLevel = st.receiverLevel;
} else {
if (compiler.options.inlineMsgSendFunctions) {
buffer.concat("(___r");
buffer.concat("(___r", node);
buffer.concat(++st.receiverLevel + "");
buffer.concat(" = (CPArray.isa.method_msgSend[\"alloc\"] || _objj_forward)(CPArray, \"alloc\"), ___r");
buffer.concat(st.receiverLevel + "");
@@ -2351,7 +2451,7 @@ ArrayLiteral: function(node, st, c) {
buffer.concat(st.receiverLevel + "");
buffer.concat(", \"initWithObjects:count:\", [");
} else {
buffer.concat("(___r");
buffer.concat("(___r", node);
buffer.concat(++st.receiverLevel + "");
buffer.concat(" = CPArray.isa.objj_msgSend0(CPArray, \"alloc\"), ___r");
buffer.concat(st.receiverLevel + "");
@@ -2410,7 +2510,7 @@ DictionaryLiteral: function(node, st, c) {
buffer.concat("}");
} else if (!keyLength) {
if (compiler.options.inlineMsgSendFunctions) {
buffer.concat("(___r");
buffer.concat("(___r", node);
buffer.concat(++st.receiverLevel + "");
buffer.concat(" = (CPDictionary.isa.method_msgSend[\"alloc\"] || _objj_forward)(CPDictionary, \"alloc\"), ___r");
buffer.concat(st.receiverLevel + "");
@@ -2435,7 +2535,7 @@ DictionaryLiteral: function(node, st, c) {
st.maxReceiverLevel = st.receiverLevel;
} else {
if (compiler.options.inlineMsgSendFunctions) {
buffer.concat("(___r");
buffer.concat("(___r", node);
buffer.concat(++st.receiverLevel + "");
buffer.concat(" = (CPDictionary.isa.method_msgSend[\"alloc\"] || _objj_forward)(CPDictionary, \"alloc\"), ___r");
buffer.concat(st.receiverLevel + "");
@@ -2445,7 +2545,7 @@ DictionaryLiteral: function(node, st, c) {
buffer.concat(st.receiverLevel + "");
buffer.concat(", \"initWithObjects:forKeys:\", [");
} else {
buffer.concat("(___r");
buffer.concat("(___r", node);
buffer.concat(++st.receiverLevel + "");
buffer.concat(" = CPDictionary.isa.objj_msgSend0(CPDictionary, \"alloc\"), ___r");
buffer.concat(st.receiverLevel + "");
@@ -2515,10 +2615,11 @@ ClassDeclarationStatement: function(node, st, c, format) {
classScope = new Scope(st),
isInterfaceDeclaration = node.type === "InterfaceDeclarationStatement",
protocols = node.protocols,
generateObjJ = compiler.options.generateObjJ;
options = compiler.options,
generateObjJ = options.generateObjJ;
compiler.imBuffer = new StringBuffer(compiler.createSourceMap, compiler.URL);
compiler.cmBuffer = new StringBuffer(compiler.createSourceMap), compiler.URL;
compiler.imBuffer = new StringBuffer(compiler.createSourceMap, compiler.URL, options.sourceMap && options.sourceMapIncludeSource ? compiler.source : null);
compiler.cmBuffer = new StringBuffer(compiler.createSourceMap, compiler.URL);
compiler.classBodyBuffer = new StringBuffer(compiler.createSourceMap, compiler.URL); // TODO: Check if this is needed
if (compiler.getTypeDef(className))
@@ -2660,7 +2761,7 @@ ClassDeclarationStatement: function(node, st, c, format) {
else
saveJSBuffer.concat(", ");
if (compiler.options.includeIvarTypeSignatures)
if (options.includeIvarTypeSignatures)
saveJSBuffer.concat("new objj_ivar(\"" + ivarName + "\", \"" + ivarType + "\")", node);
else
saveJSBuffer.concat("new objj_ivar(\"" + ivarName + "\")", node);
@@ -2708,7 +2809,8 @@ ClassDeclarationStatement: function(node, st, c, format) {
// If we have accessors add get and set methods for them
if (!generateObjJ && !isInterfaceDeclaration && hasAccessors)
{
var getterSetterBuffer = new StringBuffer(compiler.createSourceMap, compiler.URL);
// We pass false to the string buffer as we don't need source map when we create the Objective-J code for the accessors
var getterSetterBuffer = new StringBuffer(false);
// Add the class declaration to compile accessors correctly
// Remove all protocols from class declaration
@@ -2727,7 +2829,7 @@ ClassDeclarationStatement: function(node, st, c, format) {
var property = (accessors.property && accessors.property.name) || ivarName,
getterName = (accessors.getter && accessors.getter.name) || property,
getterCode = "- (" + (ivarType ? ivarType : "id") + ")" + getterName + "\n{\nreturn " + ivarName + ";\n}\n";
getterCode = "- (" + (ivarType ? ivarType : "id") + ")" + getterName + "\n{\n return " + ivarName + ";\n}\n";
getterSetterBuffer.concat(getterCode);
@@ -2743,10 +2845,10 @@ ClassDeclarationStatement: function(node, st, c, format) {
setterName = (start ? "_" : "") + "set" + property.substr(start, 1).toUpperCase() + property.substring(start + 1) + ":";
}
var setterCode = "- (void)" + setterName + "(" + (ivarType ? ivarType : "id") + ")newValue\n{\n";
var setterCode = "- (void)" + setterName + "(" + (ivarType ? ivarType : "id") + ")newValue\n{\n ";
if (accessors.copy)
setterCode += "if (" + ivarName + " !== newValue)\n" + ivarName + " = [newValue copy];\n}\n";
setterCode += "if (" + ivarName + " !== newValue)\n " + ivarName + " = [newValue copy];\n}\n";
else
setterCode += ivarName + " = newValue;\n}\n";
@@ -2757,11 +2859,26 @@ ClassDeclarationStatement: function(node, st, c, format) {
// Remove all @accessors or we will get a recursive loop in infinity
var b = getterSetterBuffer.toString().replace(/@accessors(\(.*\))?/g, "");
var imBuffer = exports.compileToIMBuffer(b, "Accessors", compiler.options);
var compilerOptions = setupOptions(options);
compilerOptions.sourceMapIncludeSource = true;
var url = compiler.url;
var filename = url && compiler.URL.substr(compiler.URL.lastIndexOf('/') + 1);
var dotIndex = filename && filename.lastIndexOf(".");
var filenameNoExt = filename && (filename.substr(0, dotIndex === -1 ? filename.length : dotIndex));
var filenameExt = filename && filename.substr(dotIndex === -1 ? filename.length : dotIndex);
var categoryname = node.categoryname && node.categoryname.id;
var imBuffer = exports.compileToIMBuffer(b, filenameNoExt + "_" + className + (categoryname ? "_" + categoryname : "") + "_Accessors" + (filenameExt || ""), compilerOptions);
// Add the accessors methods first to instance method buffer.
// This will allow manually added set and get methods to override the compiler generated
compiler.imBuffer.concat(imBuffer);
var generatedCode = imBuffer.toString();
if (compiler.createSourceMap) {
compiler.imBuffer.concat(sourceMap.SourceNode.fromStringWithSourceMap(generatedCode.code, sourceMap.SourceMapConsumer(generatedCode.map.toString())));
} else {
compiler.imBuffer.concat(generatedCode);
}
}
// We will store the ivars into the classDef first after accessors are done so we don't get a duplicate ivars error when generating accessors
@@ -2865,7 +2982,7 @@ ProtocolDeclarationStatement: function(node, st, c) {
throw compiler.error_message("Duplicate protocol " + protocolName, node.protocolname);
compiler.imBuffer = new StringBuffer(compiler.createSourceMap, compiler.URL);
compiler.cmBuffer = new StringBuffer(compiler.createSourceMap), compiler.URL;
compiler.cmBuffer = new StringBuffer(compiler.createSourceMap, compiler.URL);
if (!generate) buffer.concat(compiler.source.substring(compiler.lastPos, node.start));
@@ -3227,17 +3344,17 @@ MessageSendExpression: function(node, st, c) {
buffer.concat("[super ");
} else {
if (inlineMsgSend) {
buffer.concat("(");
buffer.concat("(", node);
buffer.concat(st.currentMethodType() === "+" ? compiler.currentSuperMetaClass : compiler.currentSuperClass);
buffer.concat(".method_dtable[\"");
buffer.concat(".method_dtable[\"", node);
buffer.concat(selector);
buffer.concat("\"] || _objj_forward)(self");
buffer.concat("\"] || _objj_forward)(self", node);
} else {
buffer.concat("objj_msgSendSuper");
buffer.concat("objj_msgSendSuper", node);
if (totalNoOfParameters < 4) {
buffer.concat("" + totalNoOfParameters);
}
buffer.concat("({ receiver:self, super_class:" + (st.currentMethodType() === "+" ? compiler.currentSuperMetaClass : compiler.currentSuperClass ) + " }");
buffer.concat("({ receiver:self, super_class:" + (st.currentMethodType() === "+" ? compiler.currentSuperMetaClass : compiler.currentSuperClass ) + " }", node);
}
}
}
@@ -3261,36 +3378,35 @@ MessageSendExpression: function(node, st, c) {
}
if (receiverIsNotSelf) {
buffer.concat("(");
buffer.concat("(", node);
c(nodeObject, st, "Expression");
buffer.concat(" == null ? null : ");
buffer.concat(" == null ? null : ", node);
}
if (inlineMsgSend)
buffer.concat("(");
buffer.concat("(", node);
c(nodeObject, st, "Expression");
} else {
receiverIsNotSelf = true;
if (!st.receiverLevel) st.receiverLevel = 0;
buffer.concat("((___r");
buffer.concat(++st.receiverLevel + "");
buffer.concat(" = ");
buffer.concat("((___r" + ++st.receiverLevel, node);
buffer.concat(" = ", node);
c(nodeObject, st, "Expression");
buffer.concat("), ___r");
buffer.concat(st.receiverLevel + "");
buffer.concat(" == null ? null : ");
buffer.concat(")", node);
buffer.concat(", ___r" + st.receiverLevel, node);
buffer.concat(" == null ? null : ", node);
if (inlineMsgSend)
buffer.concat("(");
buffer.concat("___r");
buffer.concat(st.receiverLevel + "");
buffer.concat("(", node);
buffer.concat("___r" + st.receiverLevel, node);
if (!(st.maxReceiverLevel >= st.receiverLevel))
st.maxReceiverLevel = st.receiverLevel;
}
if (inlineMsgSend) {
buffer.concat(".isa.method_msgSend[\"");
buffer.concat(selector);
buffer.concat("\"] || _objj_forward)");
} else
buffer.concat(".isa.objj_msgSend");
buffer.concat(".isa.method_msgSend[\"", node);
buffer.concat(selector, node);
buffer.concat("\"] || _objj_forward)", node);
} else {
buffer.concat(".isa.objj_msgSend", node);
}
} else {
buffer.concat(" "); // Add an extra space if it looks something like this: "return(<expression>)". No space between return and expression.
buffer.concat("objj_msgSend(");
@@ -3325,28 +3441,27 @@ MessageSendExpression: function(node, st, c) {
if (generate && !node.superObject) {
if (!inlineMsgSend) {
if (totalNoOfParameters < 4) {
buffer.concat("" + totalNoOfParameters);
buffer.concat("" + totalNoOfParameters, null);
}
}
if (receiverIsIdentifier) {
buffer.concat("(");
buffer.concat("(", node);
c(nodeObject, st, "Expression");
} else {
buffer.concat("(___r");
buffer.concat(st.receiverLevel + "");
buffer.concat("(___r" + st.receiverLevel, node);
}
}
buffer.concat(", \"");
buffer.concat(", \"", node);
buffer.concat(selector); // FIXME: sel_getUid(selector + "") ? This FIXME is from the old preprocessor compiler
buffer.concat("\"");
buffer.concat("\"", node);
if (nodeArguments) for (var i = 0; i < nodeArguments.length; i++)
{
var argument = nodeArguments[i];
buffer.concat(", ");
buffer.concat(", ", node);
if (!generate)
compiler.lastPos = argument.start;
c(argument, st, "Expression");
@@ -3360,7 +3475,7 @@ MessageSendExpression: function(node, st, c) {
{
var parameter = parameters[i];
buffer.concat(", ");
buffer.concat(", ", node);
if (!generate)
compiler.lastPos = parameter.start;
c(parameter, st, "Expression");
@@ -3372,12 +3487,12 @@ MessageSendExpression: function(node, st, c) {
if (generate && !node.superObject) {
if (receiverIsNotSelf)
buffer.concat(")");
buffer.concat(")", node);
if (!receiverIsIdentifier)
st.receiverLevel--;
}
buffer.concat(")");
buffer.concat(")", node);
}
if (!generate) compiler.lastPos = node.end;
@@ -3525,7 +3640,7 @@ TypeDefStatement: function(node, st, c) {
if (!generate)
buffer.concat(compiler.source.substring(compiler.lastPos, node.start));
buffer.concat("{var the_typedef = objj_allocateTypeDef(\"" + typeDefName + "\");");
buffer.concat("{var the_typedef = objj_allocateTypeDef(\"" + typeDefName + "\");", node);
typeDef = new TypeDef(typeDefName);
compiler.typeDefs[typeDefName] = typeDef;
+21
View File
@@ -115,3 +115,24 @@ if (!Array.prototype.indexOf)
return -1;
};
}
// ECMAScript 6 has added this. It is copied from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String
if (!String.prototype.startsWith) {
String.prototype.startsWith = function(searchString, position){
position = position || 0;
return this.substr(position, searchString.length) === searchString;
};
}
// ECMAScript 6 has added this. It is copied from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String
if (!String.prototype.endsWith) {
String.prototype.endsWith = function(searchString, position) {
var subjectString = this.toString();
if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {
position = subjectString.length;
}
position -= searchString.length;
var lastIndex = subjectString.indexOf(searchString, position);
return lastIndex !== -1 && lastIndex === position;
};
};
+1 -1
View File
@@ -1011,4 +1011,4 @@ Preprocessor.prototype.error_message = function(errorMessage)
return errorMessage + " <Context File: "+ this._URL +
(this._currentClass ? " Class: "+this._currentClass : "") +
(this._currentSelector ? " Method: "+this._currentSelector : "") +">";
}
};
+17 -1
View File
@@ -646,11 +646,15 @@ GLOBAL(objj_allocateClassPair) = function(/*Class*/ superclass, /*String*/ aName
classObject.name = aName;
classObject.info = CLS_CLASS;
classObject._UID = objj_generateObjectUID();
// It needs initialize
classObject.init = true;
metaClassObject.isa = rootClassObject.isa;
metaClassObject.name = aName;
metaClassObject.info = CLS_META;
metaClassObject._UID = objj_generateObjectUID();
// It needs initialize
metaClassObject.init = true;
return classObject;
}
@@ -837,7 +841,16 @@ GLOBAL(objj_msgSend) = function(/*id*/ aReceiver, /*SEL*/ aSelector)
var isa = aReceiver.isa;
CLASS_GET_METHOD_IMPLEMENTATION(var implementation, isa, aSelector);
// Here we should do the following line: CLASS_GET_METHOD_IMPLEMENTATION(var implementation, isa, aSelector);
// But set the 'init' attribute to 'true' when register the class pair and just check for that here is around 20% faster depending
// on environment. The '_class_initialize' function sets the 'init' attribute to 'false' when the class is initialized
if (isa.init)
_class_initialize(isa);
var method = isa.method_dtable[aSelector];
var implementation = method ? method.method_imp : _objj_forward;
#ifdef MAXIMUM_RECURSION_CHECKS
if (__objj_msgSend__StackDepth++ > MAXIMUM_RECURSION_DEPTH)
@@ -851,6 +864,9 @@ GLOBAL(objj_msgSend) = function(/*id*/ aReceiver, /*SEL*/ aSelector)
case 2: return implementation(aReceiver, aSelector);
case 3: return implementation(aReceiver, aSelector, arguments[2]);
case 4: return implementation(aReceiver, aSelector, arguments[2], arguments[3]);
case 5: return implementation(aReceiver, aSelector, arguments[2], arguments[3], arguments[4]);
case 6: return implementation(aReceiver, aSelector, arguments[2], arguments[3], arguments[4], arguments[5]);
case 7: return implementation(aReceiver, aSelector, arguments[2], arguments[3], arguments[4], arguments[5], arguments[6]);
}
return implementation.apply(aReceiver, arguments);
+21
View File
@@ -197,6 +197,27 @@ StaticResource.prototype.resourceAtURL = function(/*CFURL|String*/ aURL, /*BOOL*
return StaticResource.resourceAtURL(new CFURL(aURL, this.URL()), resolveAsDirectoriesIfNecessary);
};
/*!
* Returns an object with all the resources. Can not be directories.
*/
StaticResource.resolveResourcesAtURLs = function(/*Array of CFURL|String*/ URLs, /*Function*/ aCallback)
{
var count = URLs.length,
allResources = {};
for (var i = 0, size = count; i < size; i++)
{
var url = URLs[i];
StaticResource.resolveResourceAtURL(url, NO, function(aResource) {
allResources[url] = aResource;
if (--count === 0)
aCallback(allResources);
});
}
}
StaticResource.resolveResourceAtURL = function(/*CFURL|String*/ aURL, /*BOOL*/ isDirectory, /*Function*/ aCallback, /*Dictionary*/ aFilenameTranslateDictionary)
{
aURL = makeAbsoluteURL(aURL).absoluteURL();
+212 -72
View File
@@ -26,10 +26,6 @@
// [dammit]: acorn_loose.js
// [walk]: util/walk.js
if (typeof exports != "undefined" && !exports.acorn) {
exports.acorn = {};
exports.acorn.walk = {};
}
(function(exports, walk) {
"use strict";
@@ -134,7 +130,14 @@ if (typeof exports != "undefined" && !exports.acorn) {
// #if macro1
// #else
// #endif
// etc...
preprocess: true,
// Preprocess 'get include file' function. It should return an object with two attributes
// 'include': a string with the file to be included
// 'sourceFile': is optional and should be a string with the filename. It will
// be included in the locations property as 'source'
// Return null if file can't be found. The parser will raise an exception
preprocessGetIncludeFile: defaultGetIncludeFile,
// Preprocess add macro function
preprocessAddMacro: defaultAddMacro,
// Preprocess get macro function
@@ -150,7 +153,12 @@ if (typeof exports != "undefined" && !exports.acorn) {
macros: null,
// Turn off lineNoInErrorMessage to exclude line number in error messages
// Needs to be on to run test cases
lineNoInErrorMessage: true
lineNoInErrorMessage: true,
// Array of files to parse before parsing the main file. Each item is an
// object containing the properties 'include' and 'sourceFile'. 'include'
// has the content from the file and 'sourceFile' has the file path.
// The preprocess options must be turn on for this.
preIncludeFiles: null
};
function setOptions(opts) {
@@ -166,11 +174,18 @@ if (typeof exports != "undefined" && !exports.acorn) {
var macrosMakeBuiltin = function(name, macro, endPos) {return new Macro(name, macro, null, endPos - name.length)}
var macrosBuiltinMacros = {
__OBJJ__: function() {return macrosMakeBuiltin("__OBJJ__", options.objj ? "1" : null, tokPos)},
__BROWSER__: function() {return macrosMakeBuiltin("__BROWSER__", typeof(window) !== "undefined" ? "1" : null, tokPos)},
__LINE__: function() {return macrosMakeBuiltin("__LINE__", String(options.locations ? tokCurLine : getLineInfo(input, tokPos).line), tokPos)},
__OBJJ__: function() {return macrosMakeBuiltin("__OBJJ__", options.objj ? "1" : null, tokPos)}
}
macrosBuiltinMacros["__" + "BROWSER" + "__"] = function() {return macrosMakeBuiltin("__BROWSER__", typeof(window) !== "undefined" ? "1" : null, tokPos)};
macrosBuiltinMacros["__" + "LINE" + "__"] = function() {return macrosMakeBuiltin("__LINE__", String(options.locations ? tokCurLine : getLineInfo(input, tokPos).line), tokPos)};
macrosBuiltinMacros["__" + "DATE" + "__"] = function() {var date, day; return macrosMakeBuiltin("__DATE__", (date = new Date(), day = String(date.getDate()), ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][date.getMonth()] + (day.length > 1 ? " " : " ") + day + " " + date.getFullYear()), tokPos)};
macrosBuiltinMacros["__" + "TIME" + "__"] = function() {var date; return macrosMakeBuiltin("__TIME__", (date = new Date(), ("0" + date.getHours()).slice(-2) + ":" + ("0" + date.getMinutes()).slice(-2) + ":" + ("0" + date.getSeconds()).slice(-2)), tokPos)};
function defaultGetIncludeFile(filename) {
return {include: "#define FOO(x) x\n", sourceFile: filename};
}
function defaultAddMacro(macro) {
macros[macro.identifier] = macro;
macrosIsPredicate = null;
@@ -292,7 +307,19 @@ if (typeof exports != "undefined" && !exports.acorn) {
// tokMacroOffset is the offset to the current macro for the current token
// tokPosMacroOffset is the offset to the current macro for the current tokPos
var tokFirstStart, tokStart, tokEnd, tokMacroOffset, tokPosMacroOffset, lastTokMacroOffset;
var tokFirstStart, firstTokEnd, tokStart, tokEnd, tokMacroOffset, tokPosMacroOffset, lastTokMacroOffset;
// This is the end position for the last token in the current `input` buffer. Both regular and preprocess
// tokens count. It is '0' when entering a new buffer. It is used to determinate if a preprocess (#if) token
// is at the begining of a line
var localLastEnd;
// Is null except when a macro has ended and then contains the position of the last position in the tokens macro.
// `lastEndOfFile` contains this value for the last token. It is used to allow a semicolon to be inserted at the
// end of a macro. You can say an end of file is equivalent to a new line.
var firstEndOfFile, lastEndOfFile;
// When `options.locations` is true, these hold objects
// containing the tokens start and end line/column pairs.
@@ -337,7 +364,7 @@ if (typeof exports != "undefined" && !exports.acorn) {
// Same as input but for the current token. If options.preprocess is used
// this can differ due to macros.
var tokInput, preTokInput, tokFirstInput;
var tokInput, preTokInput, lastEndInput;
// These store the position of the previous token, which is useful
// when finishing a node and assigning its `end` position.
@@ -369,6 +396,7 @@ if (typeof exports != "undefined" && !exports.acorn) {
var preprocessParameterScope;
var preTokParameterScope;
var preprocessOverrideTokEndLoc;
var preprocessDontConcatenate; // Don't concatenate tokens when finishing preprocess tokens
// True if we are concatenating two tokens. This is needed to handle when the second part is an empty macro
// This is also used when stingifying tokens to get an empty macro
@@ -492,6 +520,7 @@ if (typeof exports != "undefined" && !exports.acorn) {
var _preWarning = {keyword: "warning"};
var _preprocessParamItem = {type: "preprocessParamItem"}
var _preprocessSkipLine = {type: "skipLine"}
var _preInclude = {keyword: "include"};
// Map keyword names to token types.
@@ -523,7 +552,7 @@ if (typeof exports != "undefined" && !exports.acorn) {
var keywordTypesPreprocessor = {"define": _preDefine, "pragma": _prePragma, "ifdef": _preIfdef, "ifndef": _preIfndef,
"undef": _preUndef, "if": _preIf, "endif": _preEndif, "else": _preElse, "elif": _preElseIf,
"defined": _preDefined, "warning": _preWarning, "error": _preError};
"defined": _preDefined, "warning": _preWarning, "error": _preError, "include": _preInclude};
// Punctuation token types. Again, the `type` property is purely for debugging.
@@ -646,7 +675,7 @@ if (typeof exports != "undefined" && !exports.acorn) {
// The preprocessor keywords.
var isKeywordPreprocessor = makePredicate("define undef pragma if ifdef ifndef else elif endif defined error warning");
var isKeywordPreprocessor = makePredicate("define undef pragma if ifdef ifndef else elif endif defined error warning include");
// ## Character categories
@@ -752,6 +781,7 @@ if (typeof exports != "undefined" && !exports.acorn) {
preprocessStack = [];
preprocessStackLastItem = null;
preprocessOnlyTransformArgumentsForLastToken = null;
preprocessDontConcatenate = false;
preNotSkipping = true;
preConcatenating = false;
preIfLevel = [];
@@ -764,15 +794,15 @@ if (typeof exports != "undefined" && !exports.acorn) {
function finishToken(type, val, overrideTokEnd) {
if (overrideTokEnd) {
tokEnd = overrideTokEnd;
firstTokEnd = tokEnd = overrideTokEnd;
if (options.locations) tokEndLoc = preprocessOverrideTokLoc;
} else {
tokEnd = tokPos;
firstTokEnd = tokEnd = tokPos;
if (options.locations) tokEndLoc = new line_loc_t;
}
tokType = type;
skipSpace();
if (options.preprocess && input.charCodeAt(tokPos) === 35 && input.charCodeAt(tokPos + 1) === 35) { // '##'
var ch = skipSpace();
if (ch === 35 && options.preprocess && input.charCodeAt(tokPos + 1) === 35) { // '##'
var val1 = val != null ? val : type.keyword || type.type;
tokPos += 2;
if (val1 != null) {
@@ -874,21 +904,26 @@ if (typeof exports != "undefined" && !exports.acorn) {
// will store all skipped comments in `tokComments`. If
// `options.trackSpaces` is on, will store the last skipped spaces in
// `tokSpaces`.
// Returns the char code of the first none whitespace or comment
function skipSpace() {
tokComments = null;
tokSpaces = null;
onlySkipSpace();
return onlySkipSpace();
}
// Returns the char code of the first none whitespace or comment
function onlySkipSpace(dontSkipEOL, dontSkipMacroBoundary, dontSkipComments) {
var spaceStart = tokPos,
lastIsNewlinePos;
lastIsNewlinePos,
ch;
for(;;) {
var ch = input.charCodeAt(tokPos);
ch = input.charCodeAt(tokPos);
if (ch === 32) { // ' '
++tokPos;
} else if (ch === 13 && !dontSkipEOL) {
} else if (ch === 13) {
if (dontSkipEOL) break;
lastIsNewlinePos = tokPos;
++tokPos;
var next = input.charCodeAt(tokPos);
@@ -899,7 +934,8 @@ if (typeof exports != "undefined" && !exports.acorn) {
++tokCurLine;
tokLineStart = tokPos;
}
} else if (ch === 10 && !dontSkipEOL) {
} else if (ch === 10) {
if (dontSkipEOL) break;
lastIsNewlinePos = tokPos;
++tokPos;
if (options.locations) {
@@ -908,7 +944,8 @@ if (typeof exports != "undefined" && !exports.acorn) {
}
} else if (ch === 9) {
++tokPos;
} else if (ch === 47 && !dontSkipComments) { // '/'
} else if (ch === 47) { // '/'
if (dontSkipComments) break;
var next = input.charCodeAt(tokPos+1);
if (next === 42) { // '*'
if (options.trackSpaces)
@@ -927,27 +964,33 @@ if (typeof exports != "undefined" && !exports.acorn) {
if (options.preprocess) {
if (dontSkipMacroBoundary) return true;
if (!preprocessStack.length) break;
// If this is the first end of file after the token save to position to allow a semicolon to be inserted
// the end of file, if needed.
if (firstEndOfFile == null) firstEndOfFile = tokPos;
// If we are at the end of the input inside a macro continue at last position
var lastItem = preprocessStack.pop();
var saveInputForPrint = input;
var saveSourceFileForPrint = sourceFile;
tokPos = lastItem.end;
input = lastItem.input;
inputLen = lastItem.inputLen;
tokCurLine = lastItem.currentLine;
tokLineStart = lastItem.currentLineStart;
/*tokStart = *///tokFirstStart = lastItem.tokStart;
//lastEnd = lastItem.lastEnd;
//lastStart = lastItem.lastStart;
preprocessOnlyTransformArgumentsForLastToken = lastItem.onlyTransformArgumentsForLastToken;
preprocessParameterScope = lastItem.parameterScope;
tokPosMacroOffset = lastItem.macroOffset;
sourceFile = lastItem.sourceFile;
firstTokEnd = lastItem.lastEnd;
// Set the last item
var lastIndex = preprocessStack.length;
preprocessStackLastItem = lastIndex ? preprocessStack[lastIndex - 1] : null;
onlySkipSpace(dontSkipEOL);
return onlySkipSpace(dontSkipEOL);
} else {
break;
}
} else if (ch === 92 && options.preprocess) { // '\'
} else if (ch === 92) { // '\'
if (!options.preprocess) break;
// Check if we have an escaped newline. We are using a relaxed treatment of escaped newlines like gcc.
// We allow spaces, horizontal and vertical tabs, and form feeds between the backslash and the subsequent newline
var pos = tokPos + 1;
@@ -969,6 +1012,7 @@ if (typeof exports != "undefined" && !exports.acorn) {
break;
}
}
return ch;
}
// ### Token reading
@@ -1028,7 +1072,7 @@ if (typeof exports != "undefined" && !exports.acorn) {
}
function readToken_lt_gt(code, finisher) { // '<>'
if (tokType === _import && options.objj && code === 60) { // '<'
if (code === 60 && (tokType === _import || preTokType === _preInclude) && options.objj) { // '<'
for (var start = tokPos + 1;;) {
var ch = input.charCodeAt(++tokPos);
if (ch === 62) // '>'
@@ -1216,6 +1260,30 @@ if (typeof exports != "undefined" && !exports.acorn) {
raise(start, "Error: " + String(preprocessEvalExpression(expr)));
break;
case _preInclude:
if (!preNotSkipping) {
return finisher(_preInclude);
}
preprocessReadToken();
if (preTokType === _string)
var localfilepath = true;
else if (preTokType ===_filename)
var localfilepath = false;
else
raise(preTokStart, "Expected \"FILENAME\" or <FILENAME>: " + (preTokType.keyword || preTokType.type));
var theFileName = preTokVal;
var includeDict = options.preprocessGetIncludeFile(preTokVal, localfilepath) || raise(preTokStart, "'" + theFileName + "' file not found");
var includeString = includeDict.include;
var includeMacro = new Macro(null, includeString, null, 0, false, null, false, null, includeDict.sourceFile);
preprocessFinishToken(_preprocess, null, null, true); // skipEOL
pushMacroToStack(includeMacro, includeMacro.macro, tokPosMacroOffset, null, null, tokPos, null, true); // isIncludeFile
skipSpace();
readToken(null, null, true); // Stealth
return;
break;
default:
if (preprocessStackLastItem) {
// If the current macro has parameters check if this word is one of them and should be stringifyed
@@ -1240,14 +1308,18 @@ if (typeof exports != "undefined" && !exports.acorn) {
else
tokSpaces = ["\n"];
}
preprocessFinishToken(_preprocess, null, null, true); // skipEOL
return readToken();
preprocessFinishToken(preTokType, null, null, true); // skipEOL
return next(true) // Stealth
}
function preprocessParseDefine() {
preprocessIsParsingPreprocess = true;
preprocessReadToken();
var macroIdentifierEnd = preTokEnd;
// We don't want to concatenate tokens when creating macros
preprocessDontConcatenate = true;
var macroIdentifier = preprocessGetIdent();
// '(' Must follow directly after identifier to be a valid macro with parameters
if (input.charCodeAt(macroIdentifierEnd) === 40) { // '('
@@ -1267,7 +1339,8 @@ if (typeof exports != "undefined" && !exports.acorn) {
while(preTokType !== _eol && preTokType !== _eof)
preprocessReadToken();
var macroString = input.slice(start, preTokStart);
preprocessDontConcatenate = false;
var macroString = preTokInput.slice(start, preTokStart);
macroString = macroString.replace(/\\/g, " ");
// If variadic get the last parameter for the variadic parameter name
options.preprocessAddMacro(new Macro(macroIdentifier, macroString, parameters, start, false, null, variadic && parameters[parameters.length - 1], positionOffset));
@@ -1436,8 +1509,8 @@ if (typeof exports != "undefined" && !exports.acorn) {
}
// Check if it is the first token on the line
lineBreak.lastIndex = 0;
var match = lineBreak.exec(input.slice(lastEnd, tokPos));
if (lastEnd !== 0 && lastEnd !== tokPos && !match) {
var match = lineBreak.exec(input.slice(localLastEnd, tokPos));
if (lastEnd !== 0 && lastEnd !== tokPos && !match && ((preprocessStackLastItem && !preprocessStackLastItem.isIncludeFile) || tokPos !== 0)) {
if (preprocessStackLastItem) {
// Stringify next token
return preprocessStringify();
@@ -1541,10 +1614,12 @@ if (typeof exports != "undefined" && !exports.acorn) {
// Returns true if it stops at a line break.
function preprocessSkipSpace(skipComments, skipEOL) {
onlySkipSpace(!skipEOL);
lineBreak.lastIndex = 0;
var match = lineBreak.exec(input.slice(tokPos, tokPos + 2));
return match && match.index === 0;
var ch = onlySkipSpace(!skipEOL);
// Can't see that this line break test is used anymore
//lineBreak.lastIndex = 0;
//var match = lineBreak.exec(input.slice(tokPos, tokPos + 2));
//return (match && match.index === 0);
return ch;
}
function preprocessSkipToElseOrEndif(skipElse) {
@@ -1586,7 +1661,7 @@ if (typeof exports != "undefined" && !exports.acorn) {
// preprocessToken is used to cancel preNotSkipping when calling from readToken_preprocess.
// FIXME: Refactor to not use this parameter preprocessToken. It is kind of confusing and it should be possible to do in another way
function preprocessReadToken(skipComments, preprocessToken, processMacros) {
function preprocessReadToken(skipComments, preprocessToken, processMacros, onlyTransformMacroArguments) {
preTokStart = tokPos;
preTokInput = input;
preTokParameterScope = preprocessParameterScope;
@@ -1629,32 +1704,67 @@ if (typeof exports != "undefined" && !exports.acorn) {
}
}
function preprocessReadWord(processMacros) {
function preprocessReadWord(processMacros, onlyTransformMacroArguments) {
var word = readWord1();
var type = _name;
if (processMacros && options.preprocess) {
var readMacroWordReturn = readMacroWord(word, preprocessNext);
var readMacroWordReturn = readMacroWord(word, preprocessNext, onlyTransformMacroArguments);
if (readMacroWordReturn === true)
return true;
}
if (!containsEsc && isKeywordPreprocessor(word)) type = keywordTypesPreprocessor[word];
preprocessFinishToken(type, word, readMacroWordReturn); // If readMacroWord returns anything except 'true' it is the real tokEndPos
preprocessFinishToken(type, word, readMacroWordReturn, false, processMacros); // If readMacroWord returns anything except 'true' it is the real tokEndPos
}
function preprocessFinishToken(type, val, overrideTokEnd, skipEOL) {
function preprocessFinishToken(type, val, overrideTokEnd, skipEOL, processMacros) {
preTokType = type;
preTokVal = val;
preTokEnd = overrideTokEnd || tokPos;
if (type !== _eol) firstTokEnd = preTokEnd;
//tokRegexpAllowed = type.beforeExpr;
preprocessSkipSpace(false, skipEOL); // Dont skip comments
var ch = preprocessSkipSpace(false, skipEOL); // Dont skip comments
if (ch === 35 && options.preprocess && !preprocessDontConcatenate && input.charCodeAt(tokPos + 1) === 35) { // '##'
var val1 = val != null ? val : type.keyword || type.type;
tokPos += 2;
if (val1 != null) {
// Save current line and current line start. This is needed when option.locations is true
var positionOffset = options.locations && new PositionOffset(tokCurLine, tokLineStart);
// Save positions on first token to get start and end correct on node if cancatenated token is invalid
var saveTokInput = tokInput, saveTokEnd = preTokEnd, saveTokStart = preTokStart, start = preTokStart + tokMacroOffset, variadicName = preprocessStackLastItem && preprocessStackLastItem.macro && preprocessStackLastItem.macro.variadicName;
skipSpace();
if (variadicName && variadicName === input.slice(tokPos, tokPos + variadicName.length)) var isVariadic = true;
preConcatenating = true;
preprocessReadToken(null, null, processMacros, 2); // 2 = Don't transform macros only arguments
preConcatenating = false;
var val2 = preTokVal != null ? preTokVal : preTokType.keyword || preTokType.type;
if (val2 != null) {
// Skip token if it is a ',' concatenated with an empty variadic parameter
if (isVariadic && val1 === "," && val2 === "") return preprocessReadToken();
var concat = "" + val1 + val2, val2TokStart = preTokStart + tokPosMacroOffset;
// If the macro defines anything add it to the preprocess input stack
var concatMacro = new Macro(null, concat, null, start, false, null, false, positionOffset);
var r = readTokenFromMacro(concatMacro, tokPosMacroOffset, preprocessStackLastItem ? preprocessStackLastItem.parameterDict : null, null, tokPos, preprocessNext, null);
// Consumed the whole macro in one bite? If not the tokenizer can't create a single token from the two concatenated tokens
if (preprocessStackLastItem && preprocessStackLastItem.macro === concatMacro) {
// FIXME: Should change this to 'preTokType' and friends
preTokType = type;
preTokStart = saveTokStart;
preTokEnd = saveTokEnd;
tokInput = saveTokInput;
tokPosMacroOffset = val2TokStart - val1.length; // reset the macro offset to the second token to get start and end correct on node
if (!isVariadic) /*raise(tokStart,*/console.log("Warning: pasting formed '" + concat + "', an invalid preprocessing token");
} else return r;
}
}
}
}
// FIXME: Find out if this is really used?
function preprocessFinishTokenSkipComments(type, val) {
preTokType = type;
preTokVal = val;
preTokEnd = tokPos;
firstTokEnd = preTokEnd = tokPos;
preprocessSkipSpace(true); // 'true' for skip comments
}
@@ -1662,10 +1772,11 @@ if (typeof exports != "undefined" && !exports.acorn) {
function preprocessNext(stealth, onlyTransformArguments, forceRegexp, processMacros) {
if (!stealth) {
preLastStart = tokStart;
preLastEnd = tokEnd;
preLastStart = preTokStart;
preLastEnd = preTokEnd;
}
return preprocessReadToken(false, false, processMacros);
localLastEnd = firstTokEnd;
return preprocessReadToken(false, false, processMacros, onlyTransformArguments);
}
// Predicate that tests whether the next token is of the given
@@ -1682,7 +1793,7 @@ if (typeof exports != "undefined" && !exports.acorn) {
// raise with errorMessage or an unexpected token error.
function preprocessExpect(type, errorMessage, processMacros) {
if (preTokType === type) preprocessReadToken(processMacros);
if (preTokType === type) preprocessNext(false, undefined, null, processMacros);
else raise(preTokStart, errorMessage || "Unexpected token");
}
@@ -1832,7 +1943,7 @@ if (typeof exports != "undefined" && !exports.acorn) {
else tokPos = tokStart + 1;
if (!stealth) {
tokFirstStart = tokStart;
tokFirstInput = input;
//tokFirstInput = input;
}
tokInput = input;
tokMacroOffset = tokPosMacroOffset;
@@ -2094,7 +2205,7 @@ if (typeof exports != "undefined" && !exports.acorn) {
// Lets look ahead to find out if we find a '##' for token concatenate
// We don't want to prescan spaces across macro boundary as the macro stack will fall apart
// So we do a special prescan if we have to cross a boundary all in the name of speed
if (onlySkipSpace(true, true)) { // don't skip EOL and don't skip macro boundary.
if (onlySkipSpace(true, true) === true) { // don't skip EOL and don't skip macro boundary.
if (preprocessPrescanFor(35, 35)) // Prescan across boundary for '##' as we crossed a boundary
onlyTransformArguments = 2;
} else if (input.charCodeAt(tokPos) === 35 && input.charCodeAt(tokPos + 1) === 35) { // '##'
@@ -2141,7 +2252,7 @@ if (typeof exports != "undefined" && !exports.acorn) {
var pos = tokPos;
var loc;
if (options.locations) loc = new line_loc_t;
if ((onlySkipSpace(true, true) && preprocessPrescanFor(40)) || input.charCodeAt(tokPos) === 40) { // '('
if ((onlySkipSpace(true, true) === true && preprocessPrescanFor(40)) || input.charCodeAt(tokPos) === 40) { // '('
nextIsParenL = true;
} else {
// We didn't find a '(' so don't transform to the macro. Return the real tokEndPos so we get correct token end values.
@@ -2279,7 +2390,7 @@ if (typeof exports != "undefined" && !exports.acorn) {
}
}
}
return scanInput.charCodeAt(scanPos) === first && (second == null || scanInput.charCodeAt(scanPos + 1) === second);
return scanInput && scanInput.charCodeAt(scanPos) === first && (second == null || scanInput.charCodeAt(scanPos + 1) === second);
}
// Push macro to stack and start read from it.
@@ -2289,20 +2400,10 @@ if (typeof exports != "undefined" && !exports.acorn) {
// If we are evaluation a macro expresion an empty macro definition means true or '1'
if(!macroString && nextFinisher === preprocessNext) macroString = "1";
if (macroString) {
preprocessStackLastItem = {macro: macro, macroOffset: macroOffset, parameterDict: parameters, /*start: macroStart,*/ end:end, inputLen: inputLen, tokStart: tokStart, onlyTransformArgumentsForLastToken: preprocessOnlyTransformArgumentsForLastToken, currentLine: tokCurLine, currentLineStart: tokLineStart/*, lastStart: lastStart, lastEnd: lastEnd*/};
if (parameterScope) preprocessStackLastItem.parameterScope = parameterScope;
preprocessStackLastItem.input = input;
preprocessStack.push(preprocessStackLastItem);
preprocessOnlyTransformArgumentsForLastToken = onlyTransformArguments;
input = macroString;
inputLen = macroString.length;
tokPosMacroOffset = macro.start;
tokPos = 0;
tokCurLine = 0;
tokLineStart = 0;
pushMacroToStack(macro, macroString, macroOffset, parameters, parameterScope, end, onlyTransformArguments);
} else if (preConcatenating) {
// If we are concatenating or stringifying and the macro is empty just make an empty string.
finishToken(_name, "");
(nextFinisher === next ? finishToken : preprocessFinishToken)(_name, "");
return true;
}
// Now read the next token
@@ -2311,6 +2412,27 @@ if (typeof exports != "undefined" && !exports.acorn) {
return true;
}
// Push macro to stack and reset tokPos etc.
// macroString is the string from the macro. It is usually 'macro.macro' but the caller can modify it if needed
// includeFile is true if the macro should be treated as a regular file. In other words don't stringify words after '#'
function pushMacroToStack(macro, macroString, macroOffset, parameters, parameterScope, end, onlyTransformArguments, isIncludeFile) {
preprocessStackLastItem = {macro: macro, macroOffset: macroOffset, parameterDict: parameters, /*start: macroStart,*/ end:end, lastEnd: localLastEnd, inputLen: inputLen, tokStart: tokStart, onlyTransformArgumentsForLastToken: preprocessOnlyTransformArgumentsForLastToken, currentLine: tokCurLine, currentLineStart: tokLineStart, sourceFile: sourceFile};
if (parameterScope) preprocessStackLastItem.parameterScope = parameterScope;
if (isIncludeFile) preprocessStackLastItem.isIncludeFile = isIncludeFile;
preprocessStackLastItem.input = input;
preprocessStack.push(preprocessStackLastItem);
preprocessOnlyTransformArgumentsForLastToken = onlyTransformArguments;
input = macroString;
inputLen = macroString.length;
tokPosMacroOffset = macro.start;
tokPos = 0;
tokCurLine = 0;
tokLineStart = 0;
firstTokEnd = 0;
localLastEnd = 0;
if (macro.sourceFile) sourceFile = macro.sourceFile;
}
// ident is the identifier name for the macro
// macro is the macro string
// parameters is an array with the parameters for the macro
@@ -2319,7 +2441,7 @@ if (typeof exports != "undefined" && !exports.acorn) {
// parameterScope is the parameter scope
// varadicName is the name of the varadic parameter if it is a varadic macro
// locationOffset is the current line that the macro starts at and the position on the line
var Macro = exports.Macro = function Macro(ident, macro, parameters, start, isArgument, parameterScope, variadicName, locationOffset) {
var Macro = exports.Macro = function Macro(ident, macro, parameters, start, isArgument, parameterScope, variadicName, locationOffset, aSourceFile) {
this.identifier = ident;
if (macro != null) this.macro = macro;
if (parameters) this.parameters = parameters;
@@ -2328,6 +2450,7 @@ if (typeof exports != "undefined" && !exports.acorn) {
if (parameterScope) this.parameterScope = parameterScope;
if (variadicName) this.variadicName = variadicName;
if (locationOffset) this.locationOffset = locationOffset;
if (aSourceFile) this.sourceFile = aSourceFile;
}
Macro.prototype.isParameterFunction = function() {
@@ -2364,11 +2487,14 @@ if (typeof exports != "undefined" && !exports.acorn) {
if (!stealth) {
lastStart = tokStart;
lastEnd = tokEnd;
lastEndInput = tokInput;
lastEndOfFile = firstEndOfFile;
lastEndLoc = tokEndLoc;
lastTokMacroOffset = tokMacroOffset;
}
nodeMessageSendObjectExpression = null;
readToken(forceRegexp, onlyTransformArguments, stealth);
localLastEnd = firstTokEnd;
firstEndOfFile = nodeMessageSendObjectExpression = null;
return readToken(forceRegexp, onlyTransformArguments, stealth);
}
// Enter strict mode. Re-reads the next token to please pedantic
@@ -2397,7 +2523,7 @@ if (typeof exports != "undefined" && !exports.acorn) {
function node_loc_t() {
this.start = tokStartLoc;
this.end = null;
if (sourceFile !== null) this.source = sourceFile;
if (sourceFile != null) this.source = sourceFile;
}
function startNode() {
@@ -2508,9 +2634,10 @@ if (typeof exports != "undefined" && !exports.acorn) {
// Test whether a semicolon can be inserted at the current position.
function canInsertSemicolon() {
//if (lastEnd !== localLastEnd) print("lastEnd: " + lastEnd + ", localLastEnd: " + localLastEnd);
return !options.strictSemicolons &&
(tokType === _eof || tokType === _braceR || newline.test(tokFirstInput.slice(lastEnd, tokFirstStart)) ||
(nodeMessageSendObjectExpression && options.objj));
(tokType === _eof || tokType === _braceR || newline.test(lastEndInput.slice(lastEnd, lastEndOfFile || tokFirstStart)) ||
(nodeMessageSendObjectExpression && options.objj) || lastEndOfFile != null);
}
// Consume a semicolon, or, failing that, see if we are allowed to
@@ -2550,9 +2677,22 @@ if (typeof exports != "undefined" && !exports.acorn) {
// statements, and wraps them in a Program node. Optionally takes a
// `program` argument. If present, the statements will be appended
// to its body instead of creating a new node.
// If there are any pre include files they will be pushed onto the macro stack
function parseTopLevel(program) {
lastStart = lastEnd = tokPos;
lastStart = localLastEnd = lastEnd = 0;
if (options.preprocess) {
var preIncludeFiles = options.preIncludeFiles;
if (preIncludeFiles && preIncludeFiles.length) for (var i = preIncludeFiles.length - 1; i >= 0; i--) {
var preIncludeFile = preIncludeFiles[i];
var preIncludeMacro = new Macro(null, preIncludeFile.include, null, 0, false, null, false, null, preIncludeFile.sourceFile);
pushMacroToStack(preIncludeMacro, preIncludeMacro.macro, 0, null, null, tokPos, null, true); // isIncludeFile
skipSpace();
}
}
if (options.locations) lastEndLoc = new line_loc_t;
inFunction = strict = null;
labels = [];
@@ -3752,4 +3892,4 @@ if (typeof exports != "undefined" && !exports.acorn) {
return finishNode(node, "ObjectiveJType");
}
})(exports.acorn, exports.acorn.walk);
})(exports.acorn || (exports.acorn = {}), exports.acorn.walk || (exports.acorn.walk = (typeof acorn !== 'undefined') && acorn.walk) || (exports.acorn.walk = {}));
+1 -1
View File
@@ -198,4 +198,4 @@ function justify(sign, prefix, string, suffix, width, leftJustify, padZeros)
function pad(n, ch)
{
return Array(MAX(0,n)+1).join(ch);
}
};
-1
View File
@@ -256,7 +256,6 @@ function reforkWithPackages()
if (additionalPackages().length > 0)
{
var cmd = serializedENV() + " " + system.args.map(OS.enquote).join(" ");
//print("REFORKING: " + cmd);
OS.exit(OS.system(cmd));
}
}