From 9b99457871fecc86bd500e83b54d7fa82d56e025 Mon Sep 17 00:00:00 2001 From: tlrobinson Date: Mon, 20 Jul 2009 18:16:17 -0700 Subject: [PATCH 1/9] Preliminary typechecking version of objj_msgSend, and preprocessor support. --- Objective-J/preprocess.js | 23 +++++++++-- Objective-J/runtime.js | 81 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 4 deletions(-) diff --git a/Objective-J/preprocess.js b/Objective-J/preprocess.js index 0032ed203..f09af79f1 100644 --- a/Objective-J/preprocess.js +++ b/Objective-J/preprocess.js @@ -578,12 +578,15 @@ objj_preprocessor.prototype.method = function(tokens) var buffer = new objj_stringBuffer(), token, selector = "", - parameters = []; + parameters = [], + types = [null]; while((token = tokens.skip_whitespace()) && token != TOKEN_OPEN_BRACE) { if (token == TOKEN_COLON) { + var type = ""; + // Colons are part of the selector name selector += token; @@ -592,18 +595,30 @@ objj_preprocessor.prototype.method = function(tokens) if (token == TOKEN_OPEN_PARENTHESIS) { // Swallow parameter/return type. Perhaps later we can use this for debugging? - while((token = tokens.skip_whitespace()) && token != TOKEN_CLOSE_PARENTHESIS) ; + while((token = tokens.skip_whitespace()) && token != TOKEN_CLOSE_PARENTHESIS) + type += token; token = tokens.skip_whitespace(); } + // Add the type. If it's empty, add null instead. + types[parameters.length+1] = type || null; + // Since this follows a colon, this must be the parameter name. parameters[parameters.length] = token; } else if (token == TOKEN_OPEN_PARENTHESIS) + { + var type = ""; + // Since :( is handled above, this must be the return type, just swallow it. - while((token = tokens.skip_whitespace()) && token != TOKEN_CLOSE_PARENTHESIS) ; + while((token = tokens.skip_whitespace()) && token != TOKEN_CLOSE_PARENTHESIS) + type += token; + + // types[0] is the return argument + types[0] = type || null; + } // Argument list ", ..." else if (token == TOKEN_COMMA) @@ -640,7 +655,7 @@ objj_preprocessor.prototype.method = function(tokens) CONCAT(buffer, ")\n{ with(self)\n{"); CONCAT(buffer, this.preprocess(tokens, NULL, TOKEN_CLOSE_BRACE, TOKEN_OPEN_BRACE)); - CONCAT(buffer, "}\n})"); + CONCAT(buffer, "}\n},"+types.toSource()+")"); return buffer; } diff --git a/Objective-J/runtime.js b/Objective-J/runtime.js index 365ab725a..fa6fb2273 100644 --- a/Objective-J/runtime.js +++ b/Objective-J/runtime.js @@ -542,3 +542,84 @@ function sel_registerName(aName) { return aName; } + + +// Type checking version of objj_msgSend: + +function objj_msgSendTypeCheck(/*id*/ aReceiver, /*SEL*/ aSelector) +{ + if (aReceiver == nil) + return nil; + + CLASS_GET_METHOD_IMPLEMENTATION(var implementation, aReceiver.isa, aSelector); + + var types = method.types; + + for (var i = 2; i < arguments.length; i++) + { + try + { + runtimeTypeCheck(types[i-1], arguments[i]); + } + catch (e) + { + objj_fprintf(warning_stream, "Type check failure: "+ + "aReceiver="+String(aReceiver).substring(0,100)+", "+ + "aSelector="+String(aSelector).substring(0,100)+", "+ + "argument #"+(i-2)+": " + e); + } + } + + var result = implementation.apply(aReceiver, arguments); + + try + { + runtimeTypeCheck(types[0], result); + } + catch (e) + { + objj_fprintf(warning_stream, "Type check failure: "+ + "aReceiver="+String(aReceiver).substring(0,100)+", "+ + "aSelector="+String(aSelector).substring(0,100)+", "+ + "return value: " + e); + } + + return result; +} + +function runtimeTypeCheck(typeName, actual) +{ + var objjClass; + + if (!typeName) + { + return; + } + if (typeName === "id") + { + return; + } + else if (typeName === "void") + { + if (actual === undefined) + return; + } + else if (objjClass = objj_getClass(typeName)) + { + if (actual && actual.isa) + { + var theClass = actual.isa; + for(; theClass; theClass = theClass.super_class) + if (theClass === objjClass) + return; + } + } + else + { + return; + } + + throw("Expected " + typeName + ", was [" + actual +"]"); +} + +objj_msgSend = objj_msgSendTypeCheck; From d7b679dc786f6942bec01d8420876b1d90172715 Mon Sep 17 00:00:00 2001 From: tlrobinson Date: Mon, 20 Jul 2009 18:39:37 -0700 Subject: [PATCH 2/9] * Move type checking to debug.js. * Use JSON.stringify for serializing types array. * Print Objective-J objects' names instead of descriptions to prevent inf recursion. --- Objective-J/debug.js | 81 +++++++++++++++++++++++++++++++++++++++ Objective-J/preprocess.js | 2 +- Objective-J/runtime.js | 81 --------------------------------------- 3 files changed, 82 insertions(+), 82 deletions(-) diff --git a/Objective-J/debug.js b/Objective-J/debug.js index cbc5fd447..dfaa573b2 100644 --- a/Objective-J/debug.js +++ b/Objective-J/debug.js @@ -171,3 +171,84 @@ function objj_profileEnd() return objj_profile_cleanup(); } + + +// Type checking version of objj_msgSend: + +function objj_msgSendTypeCheck(/*id*/ aReceiver, /*SEL*/ aSelector) +{ + if (aReceiver == nil) + return nil; + + CLASS_GET_METHOD_IMPLEMENTATION(var implementation, aReceiver.isa, aSelector); + + var types = method.types; + + for (var i = 2; i < arguments.length; i++) + { + try + { + runtimeTypeCheck(types[i-1], arguments[i]); + } + catch (e) + { + objj_fprintf(warning_stream, "Type check failure: "+ + "aReceiver="+(aReceiver.isa ? "<"+aReceiver.isa.name+">" : String(aReceiver).substring(0,100))+", "+ + "aSelector="+String(aSelector).substring(0,100)+", "+ + "argument #"+(i-2)+": " + e); + } + } + + var result = implementation.apply(aReceiver, arguments); + + try + { + runtimeTypeCheck(types[0], result); + } + catch (e) + { + objj_fprintf(warning_stream, "Type check failure: "+ + "aReceiver="+(aReceiver.isa ? "<"+aReceiver.isa.name+">" : String(aReceiver).substring(0,100))+", "+ + "aSelector="+String(aSelector).substring(0,100)+", "+ + "return value: " + e); + } + + return result; +} + +function runtimeTypeCheck(typeName, actual) +{ + var objjClass; + + if (!typeName) + { + return; + } + if (typeName === "id") + { + return; + } + else if (typeName === "void") + { + if (actual === undefined) + return; + } + else if (objjClass = objj_getClass(typeName)) + { + if (actual && actual.isa) + { + var theClass = actual.isa; + for(; theClass; theClass = theClass.super_class) + if (theClass === objjClass) + return; + } + } + else + { + return; + } + + throw("Expected " + typeName + ", was [" + ((actual && actual.isa) ? "<"+actual.isa.name+">" : actual) +"]"); +} + +objj_msgSend = objj_msgSendTypeCheck; diff --git a/Objective-J/preprocess.js b/Objective-J/preprocess.js index f09af79f1..473c70f4b 100644 --- a/Objective-J/preprocess.js +++ b/Objective-J/preprocess.js @@ -655,7 +655,7 @@ objj_preprocessor.prototype.method = function(tokens) CONCAT(buffer, ")\n{ with(self)\n{"); CONCAT(buffer, this.preprocess(tokens, NULL, TOKEN_CLOSE_BRACE, TOKEN_OPEN_BRACE)); - CONCAT(buffer, "}\n},"+types.toSource()+")"); + CONCAT(buffer, "}\n},"+JSON.stringify(types)+")"); return buffer; } diff --git a/Objective-J/runtime.js b/Objective-J/runtime.js index fa6fb2273..365ab725a 100644 --- a/Objective-J/runtime.js +++ b/Objective-J/runtime.js @@ -542,84 +542,3 @@ function sel_registerName(aName) { return aName; } - - -// Type checking version of objj_msgSend: - -function objj_msgSendTypeCheck(/*id*/ aReceiver, /*SEL*/ aSelector) -{ - if (aReceiver == nil) - return nil; - - CLASS_GET_METHOD_IMPLEMENTATION(var implementation, aReceiver.isa, aSelector); - - var types = method.types; - - for (var i = 2; i < arguments.length; i++) - { - try - { - runtimeTypeCheck(types[i-1], arguments[i]); - } - catch (e) - { - objj_fprintf(warning_stream, "Type check failure: "+ - "aReceiver="+String(aReceiver).substring(0,100)+", "+ - "aSelector="+String(aSelector).substring(0,100)+", "+ - "argument #"+(i-2)+": " + e); - } - } - - var result = implementation.apply(aReceiver, arguments); - - try - { - runtimeTypeCheck(types[0], result); - } - catch (e) - { - objj_fprintf(warning_stream, "Type check failure: "+ - "aReceiver="+String(aReceiver).substring(0,100)+", "+ - "aSelector="+String(aSelector).substring(0,100)+", "+ - "return value: " + e); - } - - return result; -} - -function runtimeTypeCheck(typeName, actual) -{ - var objjClass; - - if (!typeName) - { - return; - } - if (typeName === "id") - { - return; - } - else if (typeName === "void") - { - if (actual === undefined) - return; - } - else if (objjClass = objj_getClass(typeName)) - { - if (actual && actual.isa) - { - var theClass = actual.isa; - for(; theClass; theClass = theClass.super_class) - if (theClass === objjClass) - return; - } - } - else - { - return; - } - - throw("Expected " + typeName + ", was [" + actual +"]"); -} - -objj_msgSend = objj_msgSendTypeCheck; From 745e24d2f5a9368da0c1b64227fa626c78577d45 Mon Sep 17 00:00:00 2001 From: tlrobinson Date: Mon, 20 Jul 2009 18:42:54 -0700 Subject: [PATCH 3/9] Rename objj_msgSendTypeCheck to objj_msgSend_TypeCheck to match others --- Objective-J/debug.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Objective-J/debug.js b/Objective-J/debug.js index dfaa573b2..59563e4fa 100644 --- a/Objective-J/debug.js +++ b/Objective-J/debug.js @@ -175,7 +175,7 @@ function objj_profileEnd() // Type checking version of objj_msgSend: -function objj_msgSendTypeCheck(/*id*/ aReceiver, /*SEL*/ aSelector) +function objj_msgSend_TypeCheck(/*id*/ aReceiver, /*SEL*/ aSelector) { if (aReceiver == nil) return nil; @@ -251,4 +251,4 @@ function runtimeTypeCheck(typeName, actual) throw("Expected " + typeName + ", was [" + ((actual && actual.isa) ? "<"+actual.isa.name+">" : actual) +"]"); } -objj_msgSend = objj_msgSendTypeCheck; +objj_msgSend = objj_msgSend_TypeCheck; From 3ff945663f1033b31914da29d87a3ee7af4894dc Mon Sep 17 00:00:00 2001 From: Tom Robinson Date: Thu, 23 Jul 2009 13:24:33 -0700 Subject: [PATCH 4/9] Refactored objj_msgSend debug hooks --- Objective-J/debug.js | 344 +++++++++++++++++++++++-------------------- 1 file changed, 185 insertions(+), 159 deletions(-) diff --git a/Objective-J/debug.js b/Objective-J/debug.js index 59563e4fa..e01fbcb7a 100644 --- a/Objective-J/debug.js +++ b/Objective-J/debug.js @@ -1,103 +1,207 @@ -function objj_backtrace_format(aReceiver, aSelector) +// formatting helpers + +function objj_debug_object_format(aReceiver) { - return "[<" + GETMETA(aReceiver).name + " " + (typeof sprintf == "function" ? sprintf("%#08x", aReceiver.__address) : aReceiver.__address.toString(16)) + "> " + aSelector + "]"; + return (aReceiver && aReceiver.isa) ? sprintf("<%s %#08x>", GETMETA(aReceiver).name, aReceiver.__address) : String(aReceiver); } -function objj_msgSend_Backtrace(/*id*/ aReceiver, /*SEL*/ aSelector) +function objj_debug_message_format(aReceiver, aSelector) { - if (aReceiver == nil) - return nil; + return sprintf("[%s %s]", objj_debug_object_format(aReceiver), aSelector); +} - objj_debug_backtrace.push(objj_backtrace_format(aReceiver, aSelector)); - try +// save the original msgSend implementations so we can restore them later +var objj_msgSend_original = objj_msgSend, + objj_msgSendSuper_original = objj_msgSendSuper; + + +// decorator management functions + +// reset to default objj_msgSend* implementations +function objj_msgSend_reset() +{ + objj_msgSend = objj_msgSend_original; + objj_msgSendSuper = objj_msgSendSuper_original; +} + +// decorate both objj_msgSend and objj_msgSendSuper +function objj_msgSend_decorate() +{ + for (var i = 0; i < arguments.length; i++) { - var result = class_getMethodImplementation(aReceiver.isa, aSelector).apply(aReceiver, arguments); + objj_msgSend = arguments[i](objj_msgSend); + objj_msgSendSuper = arguments[i](objj_msgSendSuper); } - catch (anException) - { - CPLog.error("Exception " + anException + " in " + objj_backtrace_format(aReceiver, aSelector)); - objj_debug_print_backtrace(); - } - - objj_debug_backtrace.pop(); - - return result; } -function objj_msgSendSuper_Backtrace(/*id*/ aSuper, /*SEL*/ aSelector) +// reset then decorate both objj_msgSend and objj_msgSendSuper +function objj_msgSend_set_decorators() { - objj_debug_backtrace.push(objj_backtrace_format(aSuper.receiver, aSelector)); - var super_class = aSuper.super_class; - - arguments[0] = aSuper.receiver; - - try - { - var result = class_getMethodImplementation(super_class, aSelector).apply(aSuper.receiver, arguments); - } - catch (anException) - { - CPLog.error("Exception " + anException + " in " + objj_backtrace_format(aSuper.receiver, aSelector)); - objj_debug_print_backtrace(); - } - - objj_debug_backtrace.pop(); - - return result; + objj_msgSend_reset(); + objj_msgSend_decorate.apply(null, arguments); } -function objj_msgSend_Profile(/*id*/ aReceiver, /*SEL*/ aSelector) + +// backtrace decorator + +var objj_backtrace = []; +function objj_backtrace_decorator(msgSend) { - if (aReceiver == nil) - return nil; - - // profiling book keeping - var profileRecord = { - parent : objj_debug_profile, - receiver : GETMETA(aReceiver).name, - selector : aSelector, - calls : [] + return function(aReceiverOrSuper, aSelector) + { + var aReceiver = aReceiverOrSuper && (aReceiverOrSuper.receiver || aReceiverOrSuper); + + // push the receiver and selector onto the backtrace stack + objj_backtrace.push({ receiver: aReceiver, selector : aSelector }); + try + { + return msgSend.apply(null, arguments); + } + catch (anException) + { + // print the exception and backtrace + objj_fprintf(warning_stream, "Exception " + anException + " in " + objj_debug_message_format(aReceiver, aSelector)); + for (var i = 0; i < objj_backtrace.length; i++) + objj_fprintf(warning_stream, objj_debug_message_format(objj_backtrace[i].receiver, objj_backtrace[i].selector)); + } + finally + { + // make sure to always pop + objj_backtrace.pop(); + } } - objj_debug_profile.calls.push(profileRecord); - objj_debug_profile = profileRecord; - profileRecord.start = new Date(); - - var result = class_getMethodImplementation(aReceiver.isa, aSelector).apply(aReceiver, arguments); - - profileRecord.end = new Date(); - objj_debug_profile = profileRecord.parent; - - return result; } -function objj_msgSendSuper_Profile(/*id*/ aSuper, /*SEL*/ aSelector) +// type checking decorator + +var objj_typechecks_reported = {}; +function objj_typecheck_decorator(msgSend) { - // profiling book keeping - var profileRecord = { - parent : objj_debug_profile, - receiver : GETMETA(aReceiver).name, - selector : aSelector, - calls : [] + return function(aReceiverOrSuper, aSelector) + { + var aReceiver = aReceiverOrSuper && (aReceiverOrSuper.receiver || aReceiverOrSuper); + + if (!aReceiver) + return msgSend.apply(null, arguments); + + var types = aReceiver.isa.method_dtable[aSelector].types; + for (var i = 2; i < arguments.length; i++) + { + try + { + objj_debug_typecheck(types[i-1], arguments[i]); + } + catch (e) + { + var key = [GETMETA(aReceiver).name, aSelector, i, e].join(";"); + if (!objj_typechecks_reported[key]) { + objj_typechecks_reported[key] = true; + objj_fprintf(warning_stream, "Type check failed on argument " + (i-2) + " of " + objj_debug_message_format(aReceiver, aSelector) + ": " + e); + } + } + } + + var result = msgSend.apply(null, arguments); + + try + { + objj_debug_typecheck(types[0], result); + } + catch (e) + { + var key = [GETMETA(aReceiver).name, aSelector, "ret", e].join(";"); + if (!objj_typechecks_reported[key]) { + objj_typechecks_reported[key] = true; + objj_fprintf(warning_stream, "Type check failed on return val of " + objj_debug_message_format(aReceiver, aSelector) + ": " + e); + } + } + + return result; } - objj_debug_profile.calls.push(profileRecord); - objj_debug_profile = profileRecord; - profileRecord.start = new Date(); - - var super_class = aSuper.super_class; - - arguments[0] = aSuper.receiver; - - var result = class_getMethodImplementation(super_class, aSelector).apply(aSuper.receiver, arguments); - - profileRecord.end = new Date(); - objj_debug_profile = profileRecord.parent; - - return result; } -var objj_msgSend_Standard = objj_msgSend, - objj_msgSendSuper_Standard = objj_msgSendSuper; +// type checking logic: +function objj_debug_typecheck(expectedType, object) +{ + var objjClass; + + if (!expectedType) + { + return; + } + else if (expectedType === "id") + { + if (object !== undefined) + return; + } + else if (expectedType === "void") + { + if (object === undefined) + return; + } + else if (objjClass = objj_getClass(expectedType)) + { + if (object === nil) + { + return; + } + else if (object.isa) + { + var theClass = object.isa; + for (; theClass; theClass = theClass.super_class) + if (theClass === objjClass) + return; + } + } + else + { + return; + } + + var actualType; + if (object === null) + actualType = "null"; + else if (object === undefined) + actualType = "void"; + else if (object.isa) + actualType = GETMETA(object).name; + else + actualType = typeof object; + + throw ("expected=" + expectedType + ", actual=" + actualType); +} + +// profile decorator +/* +function objj_debug_profile(msgSend) +{ + return function(aReceiverOrSuper, aSelector) + { + var aReceiver = aReceiverOrSuper && (aReceiverOrSuper.receiver || aReceiverOrSuper); + + // profiling book keeping + var profileRecord = { + parent : objj_debug_profile, + receiver : aReceiver && GETMETA(aReceiver).name, + selector : aSelector, + calls : [] + } + objj_debug_profile.calls.push(profileRecord); + objj_debug_profile = profileRecord; + profileRecord.start = new Date(); + + try + { + return msgSend.apply(null, arguments); + } + finally + { + profileRecord.end = new Date(); + objj_debug_profile = profileRecord.parent; + } + } +} // FIXME: This could be much better. var objj_debug_backtrace; @@ -171,84 +275,6 @@ function objj_profileEnd() return objj_profile_cleanup(); } +*/ - -// Type checking version of objj_msgSend: - -function objj_msgSend_TypeCheck(/*id*/ aReceiver, /*SEL*/ aSelector) -{ - if (aReceiver == nil) - return nil; - - CLASS_GET_METHOD_IMPLEMENTATION(var implementation, aReceiver.isa, aSelector); - - var types = method.types; - - for (var i = 2; i < arguments.length; i++) - { - try - { - runtimeTypeCheck(types[i-1], arguments[i]); - } - catch (e) - { - objj_fprintf(warning_stream, "Type check failure: "+ - "aReceiver="+(aReceiver.isa ? "<"+aReceiver.isa.name+">" : String(aReceiver).substring(0,100))+", "+ - "aSelector="+String(aSelector).substring(0,100)+", "+ - "argument #"+(i-2)+": " + e); - } - } - - var result = implementation.apply(aReceiver, arguments); - - try - { - runtimeTypeCheck(types[0], result); - } - catch (e) - { - objj_fprintf(warning_stream, "Type check failure: "+ - "aReceiver="+(aReceiver.isa ? "<"+aReceiver.isa.name+">" : String(aReceiver).substring(0,100))+", "+ - "aSelector="+String(aSelector).substring(0,100)+", "+ - "return value: " + e); - } - - return result; -} - -function runtimeTypeCheck(typeName, actual) -{ - var objjClass; - - if (!typeName) - { - return; - } - if (typeName === "id") - { - return; - } - else if (typeName === "void") - { - if (actual === undefined) - return; - } - else if (objjClass = objj_getClass(typeName)) - { - if (actual && actual.isa) - { - var theClass = actual.isa; - for(; theClass; theClass = theClass.super_class) - if (theClass === objjClass) - return; - } - } - else - { - return; - } - - throw("Expected " + typeName + ", was [" + ((actual && actual.isa) ? "<"+actual.isa.name+">" : actual) +"]"); -} - -objj_msgSend = objj_msgSend_TypeCheck; +objj_msgSend_set_decorators(objj_typecheck_decorator, objj_backtrace_decorator); From 88be473da432591e4b95cf4dde52713e6d874915 Mon Sep 17 00:00:00 2001 From: Tom Robinson Date: Thu, 23 Jul 2009 14:14:34 -0700 Subject: [PATCH 5/9] Fixed bug in type check logic, added ability to print stack traces on type check errors --- Objective-J/debug.js | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/Objective-J/debug.js b/Objective-J/debug.js index e01fbcb7a..fddd7fed7 100644 --- a/Objective-J/debug.js +++ b/Objective-J/debug.js @@ -46,6 +46,12 @@ function objj_msgSend_set_decorators() // backtrace decorator var objj_backtrace = []; + +function objj_backtrace_print(stream) { + for (var i = 0; i < objj_backtrace.length; i++) + objj_fprintf(stream, objj_debug_message_format(objj_backtrace[i].receiver, objj_backtrace[i].selector)); +} + function objj_backtrace_decorator(msgSend) { return function(aReceiverOrSuper, aSelector) @@ -62,8 +68,7 @@ function objj_backtrace_decorator(msgSend) { // print the exception and backtrace objj_fprintf(warning_stream, "Exception " + anException + " in " + objj_debug_message_format(aReceiver, aSelector)); - for (var i = 0; i < objj_backtrace.length; i++) - objj_fprintf(warning_stream, objj_debug_message_format(objj_backtrace[i].receiver, objj_backtrace[i].selector)); + objj_backtrace_print(warning_stream); } finally { @@ -75,7 +80,9 @@ function objj_backtrace_decorator(msgSend) // type checking decorator -var objj_typechecks_reported = {}; +var objj_typechecks_reported = {}, + objj_typecheck_prints_backtrace = false; + function objj_typecheck_decorator(msgSend) { return function(aReceiverOrSuper, aSelector) @@ -98,6 +105,8 @@ function objj_typecheck_decorator(msgSend) if (!objj_typechecks_reported[key]) { objj_typechecks_reported[key] = true; objj_fprintf(warning_stream, "Type check failed on argument " + (i-2) + " of " + objj_debug_message_format(aReceiver, aSelector) + ": " + e); + if (objj_typecheck_prints_backtrace) + objj_backtrace_fprint(warning_stream); } } } @@ -114,6 +123,8 @@ function objj_typecheck_decorator(msgSend) if (!objj_typechecks_reported[key]) { objj_typechecks_reported[key] = true; objj_fprintf(warning_stream, "Type check failed on return val of " + objj_debug_message_format(aReceiver, aSelector) + ": " + e); + if (objj_typecheck_prints_backtrace) + objj_backtrace_fprint(warning_stream); } } @@ -146,7 +157,7 @@ function objj_debug_typecheck(expectedType, object) { return; } - else if (object.isa) + else if (object && object.isa) { var theClass = object.isa; for (; theClass; theClass = theClass.super_class) From 856373adecc9f3b02b7b55edbc1309a8f889b6fb Mon Sep 17 00:00:00 2001 From: Tom Robinson Date: Wed, 29 Jul 2009 18:57:18 -0700 Subject: [PATCH 6/9] Added status code checks to abort Rake early. --- AppKit/Rakefile | 1 + Objective-J/Rakefile | 4 +--- Rakefile | 7 +++++++ Tools/Rake/lib/objective-j/bundletask.rb | 3 +++ Tools/capp/Templates/ThemeDescriptor/Rakefile | 1 + common.rb | 5 +++-- 6 files changed, 16 insertions(+), 5 deletions(-) diff --git a/AppKit/Rakefile b/AppKit/Rakefile index f4f3d30cc..a93beb55c 100644 --- a/AppKit/Rakefile +++ b/AppKit/Rakefile @@ -53,6 +53,7 @@ file_d $THEME_PRODUCT => ThemeFiles << $ENVIRONMENT_PRODUCT do puts str end end + rake abort if ($? != 0) end task :build => [:build_subprojects, :AppKit, $ENVIRONMENT_PRODUCT, $THEME_PRODUCT, $ENVIRONMENT_THEME_PRODUCT] diff --git a/Objective-J/Rakefile b/Objective-J/Rakefile index f0f1782ac..dca4d0725 100644 --- a/Objective-J/Rakefile +++ b/Objective-J/Rakefile @@ -55,9 +55,7 @@ def platform_flags(*platforms) end def build_product(path, flags) - IO.popen("gcc #{flags} -E -x c -P -", "w+") do |preprocessor| - Files.select { |name| name.match(/\.js$/) }.each do |fileName| preprocessor.puts IO.read(fileName) end @@ -67,8 +65,8 @@ def build_product(path, flags) File.open(path, "w") do |file| file.write(IO.read("header.txt") + preprocessor.read) end - end + rake abort if ($? != 0) end task :build => [:Products, $ENVIRONMENT_PRODUCT, :build_subprojects] diff --git a/Rakefile b/Rakefile index 4f0a3da62..e06fdf743 100644 --- a/Rakefile +++ b/Rakefile @@ -86,7 +86,9 @@ file_d $STARTER_DOWNLOAD_APPLICATION => [$TOOLS_DOWNLOAD_ENV] do rm_rf($STARTER_DOWNLOAD_APPLICATION) mkdir_p($STARTER_DOWNLOAD) + system %{capp gen #{$STARTER_DOWNLOAD_APPLICATION} -t Application --noconfig } + rake abort if ($? != 0) # No tools means no objective-j gem rm(File.join($STARTER_DOWNLOAD_APPLICATION, 'Rakefile')) @@ -103,7 +105,9 @@ task :install => [:tools_download] do else prefix = '' end + system %{cd #{$TOOLS_DOWNLOAD} && sudo sh ./install-tools #{prefix} } + rake abort if ($? != 0) end task :test => [:build] do @@ -122,6 +126,8 @@ end task :docs do if executable_exists? "doxygen" system %{doxygen #{$DOXYGEN_CONFIG} } + rake abort if ($? != 0) + rm_rf $DOCUMENTATION_BUILD mv "debug.txt", "Documentation" mv "Documentation", $DOCUMENTATION_BUILD @@ -133,6 +139,7 @@ end task :submodules do if executable_exists? "git" system %{git submodule init && git submodule update} + rake abort if ($? != 0) else puts "Git not installed" rake abort diff --git a/Tools/Rake/lib/objective-j/bundletask.rb b/Tools/Rake/lib/objective-j/bundletask.rb index eeee33003..5fe26e939 100644 --- a/Tools/Rake/lib/objective-j/bundletask.rb +++ b/Tools/Rake/lib/objective-j/bundletask.rb @@ -390,6 +390,7 @@ module ObjectiveJ puts str end end + rake abort if ($? != 0) end { 'copy' => include_nibs, 'copied_resources' => [copied_resource] } @@ -424,6 +425,7 @@ module ObjectiveJ puts str end end + rake abort if ($? != 0) end enhance([frameworks_path]) @@ -510,6 +512,7 @@ module ObjectiveJ puts str end end + rake abort if ($? != 0) end BundleTask.compact(build_path) if needs_compact diff --git a/Tools/capp/Templates/ThemeDescriptor/Rakefile b/Tools/capp/Templates/ThemeDescriptor/Rakefile index c88a1aeae..9421af8e1 100644 --- a/Tools/capp/Templates/ThemeDescriptor/Rakefile +++ b/Tools/capp/Templates/ThemeDescriptor/Rakefile @@ -16,6 +16,7 @@ file_d $BLEND_PRODUCT => ['ThemeDescriptors.j'] do puts str end end + rake abort if ($? != 0) end task :default => [$BLEND_PRODUCT] diff --git a/common.rb b/common.rb index 1ae320f40..eeb3ac534 100644 --- a/common.rb +++ b/common.rb @@ -77,8 +77,8 @@ end def subrake(directories, task_name) directories.each do |directory| if (File.directory?(directory) && File.file?(File.join(directory, "Rakefile"))) - ok = system(%{cd #{directory} && #{$serialized_env} #{$0} #{task_name}}) - rake abort unless ok + system(%{cd #{directory} && #{$serialized_env} #{$0} #{task_name}}) + rake abort if ($? != 0) else puts "warning: subrake missing: " + directory +" (this is not necessarily an error, "+directory+" may be optional)" end @@ -147,4 +147,5 @@ task :clobberall => ['clobber-all'] def spawn_rake(task_name) system %{#{$serialized_env} #{$0} #{task_name}} + rake abort if ($? != 0) end From 2bb6da51327d27dd51d1b30c53729cd1e5761ddb Mon Sep 17 00:00:00 2001 From: Tom Robinson Date: Wed, 29 Jul 2009 19:21:17 -0700 Subject: [PATCH 7/9] Undoing this so Ross stops complaining. --- Tools/Rake/lib/objective-j/bundletask.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/Rake/lib/objective-j/bundletask.rb b/Tools/Rake/lib/objective-j/bundletask.rb index 5fe26e939..95b77e138 100644 --- a/Tools/Rake/lib/objective-j/bundletask.rb +++ b/Tools/Rake/lib/objective-j/bundletask.rb @@ -390,7 +390,7 @@ module ObjectiveJ puts str end end - rake abort if ($? != 0) + #rake abort if ($? != 0) end { 'copy' => include_nibs, 'copied_resources' => [copied_resource] } From 3b8664e6ff977308ef67769de873f5ab27fa993c Mon Sep 17 00:00:00 2001 From: Tom Robinson Date: Wed, 29 Jul 2009 19:23:32 -0700 Subject: [PATCH 8/9] Disable typechecking by default --- Objective-J/debug.js | 107 -------------------------------------- Objective-J/preprocess.js | 8 ++- 2 files changed, 6 insertions(+), 109 deletions(-) diff --git a/Objective-J/debug.js b/Objective-J/debug.js index fddd7fed7..bd23ab7ae 100644 --- a/Objective-J/debug.js +++ b/Objective-J/debug.js @@ -182,110 +182,3 @@ function objj_debug_typecheck(expectedType, object) throw ("expected=" + expectedType + ", actual=" + actualType); } - -// profile decorator -/* -function objj_debug_profile(msgSend) -{ - return function(aReceiverOrSuper, aSelector) - { - var aReceiver = aReceiverOrSuper && (aReceiverOrSuper.receiver || aReceiverOrSuper); - - // profiling book keeping - var profileRecord = { - parent : objj_debug_profile, - receiver : aReceiver && GETMETA(aReceiver).name, - selector : aSelector, - calls : [] - } - objj_debug_profile.calls.push(profileRecord); - objj_debug_profile = profileRecord; - profileRecord.start = new Date(); - - try - { - return msgSend.apply(null, arguments); - } - finally - { - profileRecord.end = new Date(); - objj_debug_profile = profileRecord.parent; - } - } -} - -// FIXME: This could be much better. -var objj_debug_backtrace; - -function objj_backtrace_set_enabled(enabled) -{ - if (enabled) - { - objj_debug_backtrace = []; - objj_msgSend = objj_msgSend_Backtrace; - objj_msgSendSuper = objj_msgSendSuper_Backtrace; - } - else - { - objj_msgSend = objj_msgSend_Standard; - objj_msgSendSuper = objj_msgSendSuper_Standard; - } -} - -function objj_debug_print_backtrace() -{ - alert(objj_debug_backtrace_string()); -} - -function objj_debug_backtrace_string() -{ - return objj_debug_backtrace ? objj_debug_backtrace.join("\n") : ""; -} - -var objj_debug_profile = null, - objj_currently_profiling = false, - objj_profile_cleanup; - -function objj_profile(title) -{ - if (objj_currently_profiling) - return; - - var objj_msgSend_profile_saved = objj_msgSend, - objj_msgSendSuper_profile_saved = objj_msgSendSuper; - - objj_msgSend = objj_msgSend_Profile; - objj_msgSendSuper = objj_msgSendSuper_Profile; - - var root = { calls: [] }; - objj_debug_profile = root; - - var context = { - start : new Date(), - title : title, - profile : root - }; - - objj_profile_cleanup = function() { - objj_msgSend = objj_msgSend_profile_saved; - objj_msgSendSuper = objj_msgSendSuper_profile_saved; - context.end = new Date(); - return context; - } - - objj_currently_profiling = true; -} - -function objj_profileEnd() -{ - if (!objj_currently_profiling) - return; - - objj_debug_profile = null; - objj_currently_profiling = false; - - return objj_profile_cleanup(); -} -*/ - -objj_msgSend_set_decorators(objj_typecheck_decorator, objj_backtrace_decorator); diff --git a/Objective-J/preprocess.js b/Objective-J/preprocess.js index 0dd3cc93f..07de33827 100644 --- a/Objective-J/preprocess.js +++ b/Objective-J/preprocess.js @@ -20,7 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -var OBJJ_PREPROCESSOR_DEBUG_SYMBOLS = 1 << 0; +var OBJJ_PREPROCESSOR_DEBUG_SYMBOLS = 1 << 0, + OBJJ_PREPROCESSOR_TYPE_SIGNATURES = 1 << 1; function objj_preprocess(/*String*/ aString, /*objj_bundle*/ aBundle, /*objj_file*/ aSourceFile, /*unsigned*/ flags) { @@ -669,7 +670,10 @@ objj_preprocessor.prototype.method = function(tokens) CONCAT(buffer, ")\n{ with(self)\n{"); CONCAT(buffer, this.preprocess(tokens, NULL, TOKEN_CLOSE_BRACE, TOKEN_OPEN_BRACE)); - CONCAT(buffer, "}\n},"+JSON.stringify(types)+")"); + CONCAT(buffer, "}\n}"); + if (this._flags & OBJJ_PREPROCESSOR_TYPE_SIGNATURES) + CONCAT(buffer, ","+JSON.stringify(types)); + CONCAT(buffer, ")"); return buffer; } From 0c349a8d7f67b185747290595dbd666fb841408d Mon Sep 17 00:00:00 2001 From: Tom Robinson Date: Wed, 29 Jul 2009 20:23:40 -0700 Subject: [PATCH 9/9] Add option to enable type checking in index-debug.html. --- Objective-J/debug.js | 4 ++-- Objective-J/preprocess.js | 3 ++- .../capp/Templates/Application/index-debug.html | 17 ++++++++++++++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/Objective-J/debug.js b/Objective-J/debug.js index bd23ab7ae..2c7624464 100644 --- a/Objective-J/debug.js +++ b/Objective-J/debug.js @@ -106,7 +106,7 @@ function objj_typecheck_decorator(msgSend) objj_typechecks_reported[key] = true; objj_fprintf(warning_stream, "Type check failed on argument " + (i-2) + " of " + objj_debug_message_format(aReceiver, aSelector) + ": " + e); if (objj_typecheck_prints_backtrace) - objj_backtrace_fprint(warning_stream); + objj_backtrace_print(warning_stream); } } } @@ -124,7 +124,7 @@ function objj_typecheck_decorator(msgSend) objj_typechecks_reported[key] = true; objj_fprintf(warning_stream, "Type check failed on return val of " + objj_debug_message_format(aReceiver, aSelector) + ": " + e); if (objj_typecheck_prints_backtrace) - objj_backtrace_fprint(warning_stream); + objj_backtrace_print(warning_stream); } } diff --git a/Objective-J/preprocess.js b/Objective-J/preprocess.js index 07de33827..ad96215f9 100644 --- a/Objective-J/preprocess.js +++ b/Objective-J/preprocess.js @@ -671,7 +671,8 @@ objj_preprocessor.prototype.method = function(tokens) CONCAT(buffer, ")\n{ with(self)\n{"); CONCAT(buffer, this.preprocess(tokens, NULL, TOKEN_CLOSE_BRACE, TOKEN_OPEN_BRACE)); CONCAT(buffer, "}\n}"); - if (this._flags & OBJJ_PREPROCESSOR_TYPE_SIGNATURES) + // TODO: actually use OBJJ_PREPROCESSOR_TYPE_SIGNATURES flag instead of tying to OBJJ_PREPROCESSOR_DEBUG_SYMBOLS + if (this._flags & OBJJ_PREPROCESSOR_DEBUG_SYMBOLS) //OBJJ_PREPROCESSOR_TYPE_SIGNATURES) CONCAT(buffer, ","+JSON.stringify(types)); CONCAT(buffer, ")"); diff --git a/Tools/capp/Templates/Application/index-debug.html b/Tools/capp/Templates/Application/index-debug.html index 5ebc00c9a..54b8f7fbe 100644 --- a/Tools/capp/Templates/Application/index-debug.html +++ b/Tools/capp/Templates/Application/index-debug.html @@ -21,7 +21,22 @@ - + + +