mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-09-25 11:50:42 +00:00
Refactor objj-analysis-tools a bit.
This commit is contained in:
+14
-38
@@ -11,7 +11,8 @@ var FILE = require("file");
|
||||
var OS = require("os");
|
||||
var DOM = require("browser/dom");
|
||||
var UTIL = require("util");
|
||||
var INTERPRETER = require("interpreter");
|
||||
|
||||
var stream = require("term").stream;
|
||||
|
||||
var serializer = new DOM.XMLSerializer();
|
||||
|
||||
@@ -146,14 +147,12 @@ function pressEnvironment(rootPath, outputFiles, environment, options) {
|
||||
CPLog.info("Frameworks: " + frameworks);
|
||||
CPLog.info("Environment: " + environment);
|
||||
|
||||
// get a Rhino context
|
||||
var context = new INTERPRETER.Context();
|
||||
var scope = setupObjectiveJ(context);
|
||||
var analyzer = new ObjectiveJRuntimeAnalyzer(rootPath);
|
||||
|
||||
var _OBJJ = context.global.require("objective-j");
|
||||
var _OBJJ = analyzer.require("objective-j");
|
||||
|
||||
// include paths:
|
||||
context.global.OBJJ_INCLUDE_PATHS = frameworks;
|
||||
analyzer.context.global.OBJJ_INCLUDE_PATHS = frameworks;
|
||||
// environments:
|
||||
_OBJJ.environments = function() { return [environment, "ObjJ"] };
|
||||
|
||||
@@ -161,43 +160,17 @@ function pressEnvironment(rootPath, outputFiles, environment, options) {
|
||||
// FIXME: what's the best way to determine which cibs to look in?
|
||||
var cibs = FILE.glob(rootPath.join("**", "*.cib")).filter(function(path) { return !(/Frameworks/).test(path); });
|
||||
|
||||
// flattening bookkeeping. keep track of the bundles and evaled code (in the correct order!)
|
||||
var bundleArchiveResponses = [];
|
||||
var exectuableResponses = [];
|
||||
var evaledFragments = [];
|
||||
|
||||
// here we hook into didReceiveBundleResponse to record the responses for --flattening
|
||||
/*
|
||||
functionHookBefore(scope.objj_search.prototype, "didReceiveBundleResponse", function(aResponse) {
|
||||
var response = {
|
||||
success : aResponse.success,
|
||||
filePath : rootPath.relative(aResponse.filePath).toString()
|
||||
};
|
||||
|
||||
if (aResponse.success) {
|
||||
var xmlString = serializer.serializeToString(aResponse.xml);
|
||||
response.text = CPPropertyListCreate280NorthData(CPPropertyListCreateFromXMLData({ string: xmlString })).string;
|
||||
}
|
||||
|
||||
bundleArchiveResponses.push(response);
|
||||
});
|
||||
|
||||
functionHookBefore(scope.objj_search.prototype, "didReceiveExecutableResponse", function(aResponse) {
|
||||
exectuableResponses.push(aResponse);
|
||||
});
|
||||
*/
|
||||
|
||||
// lets just use the Context object as our con
|
||||
context.rootPath = rootPath;
|
||||
context.scope = scope;
|
||||
|
||||
// phase 1: get global defines
|
||||
CPLog.error("PHASE 1: Loading application...");
|
||||
|
||||
var globals = findGlobalDefines(context, mainPath, evaledFragments);
|
||||
analyzer.initializeGlobalRecorder();
|
||||
|
||||
analyzer.load(mainPath);
|
||||
|
||||
analyzer.finishLoading();
|
||||
|
||||
// coalesce the results
|
||||
var dependencies = coalesceGlobalDefines(globals);
|
||||
var dependencies = analyzer.globalsToFilesMapping();
|
||||
|
||||
// log identifer => files defining
|
||||
CPLog.trace("Global defines:");
|
||||
@@ -205,6 +178,9 @@ function pressEnvironment(rootPath, outputFiles, environment, options) {
|
||||
CPLog.trace(" " + identifier + " => " + rootPath.relative(dependencies[identifier]));
|
||||
});
|
||||
|
||||
CPLog.error("NOT YET IMPLEMENTED");
|
||||
OS.exit(1);
|
||||
|
||||
// phase 2: walk the dependency tree (both imports and references) to determine exactly which files need to be included
|
||||
CPLog.error("PHASE 2: Walk dependency tree...");
|
||||
|
||||
|
||||
+113
-106
@@ -1,4 +1,115 @@
|
||||
var FILE = require("file");
|
||||
var Context = require("interpreter").Context;
|
||||
|
||||
function ObjectiveJRuntimeAnalyzer(rootPath)
|
||||
{
|
||||
this.rootPath = rootPath;
|
||||
this.context = new Context();
|
||||
|
||||
this.scope = setupObjectiveJ(this.context);
|
||||
|
||||
this.require = this.context.global.require;
|
||||
}
|
||||
|
||||
ObjectiveJRuntimeAnalyzer.prototype.initializeGlobalRecorder = function()
|
||||
{
|
||||
this.initializeGlobalRecorder = function(){}; // run once
|
||||
|
||||
this.ignore = cloneProperties(this.scope, true);
|
||||
this.ignore['bundle'] = true;
|
||||
|
||||
this.files = {};
|
||||
var evaluatingPaths = [];
|
||||
|
||||
var before = null;
|
||||
var currentFile = null;
|
||||
|
||||
var self = this;
|
||||
|
||||
// a function to record changes to the global, then reset the scope
|
||||
function recordAndReset() {
|
||||
// system.stderr.write(".").flush();
|
||||
|
||||
var after = cloneProperties(self.scope);
|
||||
|
||||
if (before) {
|
||||
self.files[currentFile] = self.files[currentFile] || {};
|
||||
self.files[currentFile].globals = self.files[currentFile].global || {};
|
||||
|
||||
diff({
|
||||
before : before,
|
||||
after : after,
|
||||
ignore : self.ignore,
|
||||
added : self.files[currentFile].globals,
|
||||
changed : self.files[currentFile].globals
|
||||
});
|
||||
}
|
||||
|
||||
before = after;
|
||||
}
|
||||
|
||||
var _OBJJ = this.require("objective-j");
|
||||
var _fileExecuterForPath = _OBJJ.fileExecuterForPath;
|
||||
_OBJJ.fileExecuterForPath = function(/*String*/ referencePath) {
|
||||
var fileExecutor = _fileExecuterForPath.apply(this, arguments);
|
||||
return function(/*String*/ aPath, /*BOOL*/ isLocal, /*BOOL*/ shouldForce) {
|
||||
recordAndReset();
|
||||
|
||||
evaluatingPaths.push(currentFile);
|
||||
currentFile = FILE.normal(FILE.join(referencePath, aPath));
|
||||
|
||||
system.stderr.write(">").flush();
|
||||
fileExecutor.apply(this, arguments);
|
||||
system.stderr.write("<").flush();
|
||||
|
||||
recordAndReset();
|
||||
|
||||
currentFile = evaluatingPaths.pop();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
ObjectiveJRuntimeAnalyzer.prototype.load = function(path)
|
||||
{
|
||||
this.require("objective-j").objj_eval(
|
||||
"("+(function(path) {
|
||||
fileImporterForPath("/")(path, true, function() {
|
||||
print("Done importing and evaluating: " + path);
|
||||
});
|
||||
})+")"
|
||||
)(path);
|
||||
}
|
||||
|
||||
ObjectiveJRuntimeAnalyzer.prototype.finishLoading = function(path)
|
||||
|
||||
// run the "event loop"
|
||||
this.require('browser/timeout').serviceTimeouts();
|
||||
}
|
||||
|
||||
ObjectiveJRuntimeAnalyzer.prototype.globalsToFilesMapping = function()
|
||||
{
|
||||
// takes a hash mapping from file names to hashes of global names defined in each file
|
||||
// globals = { fileName { globalName : true }}
|
||||
// returns a hash mapping from global names to arrays of file names in which those globals are defined
|
||||
// dependencies = { globalName : [fileName] }
|
||||
var globals = {};
|
||||
for (var fileName in this.files) {
|
||||
for (var globalName in this.files[fileName].globals)
|
||||
(globals[globalName] = globals[globalName] || []).push(fileName);
|
||||
}
|
||||
return globals;
|
||||
}
|
||||
|
||||
ObjectiveJRuntimeAnalyzer.prototype.filesToGlobalsMapping = function()
|
||||
{
|
||||
var files = {};
|
||||
for (var fileName in this.files) {
|
||||
files[fileName] = {};
|
||||
for (var globalName in this.files[fileName].globals)
|
||||
files[fileName][globalName] = true;
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
/*
|
||||
param context includes
|
||||
@@ -57,7 +168,7 @@ function traverseDependencies(context, file)
|
||||
if (fragment.type & FRAGMENT_CODE)
|
||||
{
|
||||
var referencedTokens = uniqueTokens(fragment.info);
|
||||
|
||||
|
||||
markFilesReferencedByTokens(referencedTokens, context.dependencies, referencedFiles);
|
||||
}
|
||||
else if (fragment.type & FRAGMENT_FILE)
|
||||
@@ -219,110 +330,6 @@ function findImportInObjjFiles(scope, fragment)
|
||||
}
|
||||
@end
|
||||
|
||||
// given a fresh scope and the path to a root source file, determine which files define each global variable
|
||||
function findGlobalDefines(context, mainPath, evaledFragments, bundleCallback)
|
||||
{
|
||||
var ignore = cloneProperties(context.scope, true);
|
||||
ignore['bundle'] = true;
|
||||
|
||||
var dependencies = {};
|
||||
var evaluatingPaths = [];
|
||||
|
||||
var before = null;
|
||||
var currentFile = null;
|
||||
|
||||
// a function to record changes to the global, then reset the scope
|
||||
function recordAndReset() {
|
||||
// system.stderr.write(".").flush();
|
||||
|
||||
var after = cloneProperties(context.scope);
|
||||
|
||||
if (before) {
|
||||
dependencies[currentFile] = dependencies[currentFile] || {};
|
||||
diff({
|
||||
before : before,
|
||||
after : after,
|
||||
ignore : ignore,
|
||||
added : dependencies[currentFile],
|
||||
changed : dependencies[currentFile]
|
||||
});
|
||||
}
|
||||
|
||||
before = after;
|
||||
}
|
||||
|
||||
var _OBJJ = context.scope.require("objective-j");
|
||||
var _fileExecuterForPath = _OBJJ.fileExecuterForPath;
|
||||
_OBJJ.fileExecuterForPath = function(/*String*/ referencePath) {
|
||||
var fileExecutor = _fileExecuterForPath.apply(this, arguments);
|
||||
return function(/*String*/ aPath, /*BOOL*/ isLocal, /*BOOL*/ shouldForce) {
|
||||
recordAndReset();
|
||||
|
||||
evaluatingPaths.push(currentFile);
|
||||
currentFile = referencePath + "/" + aPath;
|
||||
|
||||
system.stderr.write(">").flush();
|
||||
fileExecutor.apply(this, arguments);
|
||||
system.stderr.write("<").flush();
|
||||
|
||||
recordAndReset();
|
||||
|
||||
currentFile = evaluatingPaths.pop();
|
||||
};
|
||||
}
|
||||
|
||||
var bundleDelegate = [[PressBundleDelgate alloc] initWithCallback:bundleCallback];
|
||||
var bundlePaths = [];
|
||||
|
||||
(context.global.require("objective-j").objj_eval(
|
||||
"("+(function(mainPath, bundleDelegate, bundlePaths) {
|
||||
fileImporterForPath("/")(mainPath, true, function() {
|
||||
print("Done importing and evaluating: " + mainPath);
|
||||
// bundlePaths = bundlePaths || [];
|
||||
|
||||
// load default theme bundle
|
||||
// var themePath = [[CPBundle bundleForClass:[CPApplication class]] pathForResource:[CPApplication defaultThemeName]];
|
||||
// var themeBundle = [[CPBundle alloc] initWithPath:themePath + "/Info.plist"];
|
||||
// [themeBundle loadWithDelegate:bundleDelegate];
|
||||
|
||||
// load additional bundles
|
||||
// bundlePaths.forEach(function(bundlePath) {
|
||||
// var bundle = [[CPBundle alloc] initWithPath:bundlePath];
|
||||
// [bundle loadWithDelegate:bundleDelegate];
|
||||
// });
|
||||
});
|
||||
})+")"
|
||||
))(mainPath, bundleDelegate, bundlePaths);
|
||||
|
||||
// run the "event loop"
|
||||
context.scope.require('browser/timeout').serviceTimeouts();
|
||||
|
||||
print(JSON.stringify(dependencies, null, 4));
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
// takes a hash mapping from file names to hashes of global names defined in each file
|
||||
// globals = { fileName { globalName : true }}
|
||||
// returns a hash mapping from global names to arrays of file names in which those globals are defined
|
||||
// dependencies = { globalName : [fileName] }
|
||||
function coalesceGlobalDefines(globals)
|
||||
{
|
||||
var dependencies = {};
|
||||
for (var fileName in globals)
|
||||
{
|
||||
var fileGlobals = globals[fileName];
|
||||
|
||||
for (var globalName in fileGlobals)
|
||||
{
|
||||
if (!dependencies[globalName])
|
||||
dependencies[globalName] = [];
|
||||
dependencies[globalName].push(fileName);
|
||||
}
|
||||
}
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
// create a new scope loaded with Narwhal and Objective-J
|
||||
function setupObjectiveJ(context, debug)
|
||||
{
|
||||
@@ -333,7 +340,7 @@ function setupObjectiveJ(context, debug)
|
||||
// load the bootstrap.js for narwhal-rhino
|
||||
var bootstrapPath = FILE.join(context.global.NARWHAL_ENGINE_HOME, "bootstrap.js");
|
||||
context.evalFile(bootstrapPath);
|
||||
|
||||
|
||||
context.global.require("browser");
|
||||
|
||||
// get the Objective-J module from this scope, return the window object.
|
||||
|
||||
Reference in New Issue
Block a user