|
@@ -162,6 +162,39 @@ function OrganizeBrik(brikz, st) {
|
|
|
};
|
|
|
}
|
|
|
|
|
|
+function DNUBrik(brikz, st) {
|
|
|
+
|
|
|
+ /* Method not implemented handlers */
|
|
|
+
|
|
|
+ brikz.ensure("messageSend");
|
|
|
+
|
|
|
+ this.methods = [];
|
|
|
+ this.selectors = [];
|
|
|
+
|
|
|
+ this.get = function (string) {
|
|
|
+ var index = this.selectors.indexOf(string);
|
|
|
+ if(index !== -1) {
|
|
|
+ return this.methods[index];
|
|
|
+ }
|
|
|
+ this.selectors.push(string);
|
|
|
+ var selector = st.selector(string);
|
|
|
+ var method = {jsSelector: selector, fn: this.createHandler(selector)};
|
|
|
+ this.methods.push(method);
|
|
|
+ return method;
|
|
|
+ };
|
|
|
+
|
|
|
+ /* Dnu handler method */
|
|
|
+
|
|
|
+ this.createHandler = function (selector) {
|
|
|
+ var handler = function() {
|
|
|
+ var args = Array.prototype.slice.call(arguments);
|
|
|
+ return brikz.messageSend.messageNotUnderstood(this, selector, args);
|
|
|
+ };
|
|
|
+
|
|
|
+ return handler;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
var nil = new SmalltalkNil();
|
|
|
|
|
|
function SmalltalkFactory(brikz, st) {
|
|
@@ -170,6 +203,7 @@ function SmalltalkFactory(brikz, st) {
|
|
|
|
|
|
brikz.ensure("selectorConversion");
|
|
|
var org = brikz.ensure("organize");
|
|
|
+ var dnu = brikz.ensure("dnu");
|
|
|
|
|
|
/* This is the current call context object. While it is publicly available,
|
|
|
Use smalltalk.getThisContext() instead which will answer a safe copy of
|
|
@@ -203,36 +237,6 @@ function SmalltalkFactory(brikz, st) {
|
|
|
var classes = [];
|
|
|
var wrappedClasses = [];
|
|
|
|
|
|
- /* Method not implemented handlers */
|
|
|
-
|
|
|
- var dnu = {
|
|
|
- methods: [],
|
|
|
- selectors: [],
|
|
|
-
|
|
|
- get: function (string) {
|
|
|
- var index = this.selectors.indexOf(string);
|
|
|
- if(index !== -1) {
|
|
|
- return this.methods[index];
|
|
|
- }
|
|
|
- this.selectors.push(string);
|
|
|
- var selector = st.selector(string);
|
|
|
- var method = {jsSelector: selector, fn: this.createHandler(selector)};
|
|
|
- this.methods.push(method);
|
|
|
- return method;
|
|
|
- },
|
|
|
-
|
|
|
- /* Dnu handler method */
|
|
|
-
|
|
|
- createHandler: function (selector) {
|
|
|
- var handler = function() {
|
|
|
- var args = Array.prototype.slice.call(arguments);
|
|
|
- return messageNotUnderstood(this, selector, args);
|
|
|
- };
|
|
|
-
|
|
|
- return handler;
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
/* Answer all method selectors based on dnu handlers */
|
|
|
|
|
|
st.allSelectors = function() {
|
|
@@ -618,22 +622,6 @@ function SmalltalkFactory(brikz, st) {
|
|
|
// This is handled by #removeCompiledMethod
|
|
|
};
|
|
|
|
|
|
- /* Handles unhandled errors during message sends */
|
|
|
- // simply send the message and handle #dnu:
|
|
|
-
|
|
|
- st.send = function(receiver, selector, args, klass) {
|
|
|
- var method;
|
|
|
- if(receiver === null) {
|
|
|
- receiver = nil;
|
|
|
- }
|
|
|
- method = klass ? klass.fn.prototype[selector] : receiver.klass && receiver[selector];
|
|
|
- if(method) {
|
|
|
- return method.apply(receiver, args);
|
|
|
- } else {
|
|
|
- return messageNotUnderstood(receiver, selector, args);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
st.withContext = function(worker, setup) {
|
|
|
if(st.thisContext) {
|
|
|
st.thisContext.pc++;
|
|
@@ -674,56 +662,6 @@ function SmalltalkFactory(brikz, st) {
|
|
|
st.ErrorHandler._current()._handleError_(error);
|
|
|
}
|
|
|
|
|
|
- /* Handles #dnu: *and* JavaScript method calls.
|
|
|
- if the receiver has no klass, we consider it a JS object (outside of the
|
|
|
- Amber system). Else assume that the receiver understands #doesNotUnderstand: */
|
|
|
-
|
|
|
- function messageNotUnderstood(receiver, selector, args) {
|
|
|
- /* Handles JS method calls. */
|
|
|
- if(receiver.klass === undefined || receiver.allowJavaScriptCalls) {
|
|
|
- return callJavaScriptMethod(receiver, selector, args);
|
|
|
- }
|
|
|
-
|
|
|
- /* Handles not understood messages. Also see the Amber counter-part
|
|
|
- Object>>doesNotUnderstand: */
|
|
|
-
|
|
|
- return receiver._doesNotUnderstand_(
|
|
|
- st.Message._new()
|
|
|
- ._selector_(st.convertSelector(selector))
|
|
|
- ._arguments_(args)
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- /* Call a method of a JS object, or answer a property if it exists.
|
|
|
- Else try wrapping a JSObjectProxy around the receiver.
|
|
|
-
|
|
|
- If the object property is a function, then call it, except if it starts with
|
|
|
- an uppercase character (we probably want to answer the function itself in this
|
|
|
- case and send it #new from Amber).
|
|
|
-
|
|
|
- Converts keyword-based selectors by using the first
|
|
|
- keyword only, but keeping all message arguments.
|
|
|
-
|
|
|
- Example:
|
|
|
- "self do: aBlock with: anObject" -> "self.do(aBlock, anObject)" */
|
|
|
-
|
|
|
- function callJavaScriptMethod(receiver, selector, args) {
|
|
|
- var jsSelector = selector._asJavaScriptSelector();
|
|
|
- var jsProperty = receiver[jsSelector];
|
|
|
- if(typeof jsProperty === "function" && !/^[A-Z]/.test(jsSelector)) {
|
|
|
- return jsProperty.apply(receiver, args);
|
|
|
- } else if(jsProperty !== undefined) {
|
|
|
- if(args[0]) {
|
|
|
- receiver[jsSelector] = args[0];
|
|
|
- return nil;
|
|
|
- } else {
|
|
|
- return jsProperty;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return st.send(st.JSObjectProxy._on_(receiver), selector, args);
|
|
|
- }
|
|
|
-
|
|
|
/* Handle thisContext pseudo variable */
|
|
|
|
|
|
st.getThisContext = function() {
|
|
@@ -791,6 +729,77 @@ function SmalltalkFactory(brikz, st) {
|
|
|
};
|
|
|
}
|
|
|
|
|
|
+function MessageSendBrik(brikz, st) {
|
|
|
+
|
|
|
+ /* Handles unhandled errors during message sends */
|
|
|
+ // simply send the message and handle #dnu:
|
|
|
+
|
|
|
+ st.send = function(receiver, selector, args, klass) {
|
|
|
+ var method;
|
|
|
+ if(receiver === null) {
|
|
|
+ receiver = nil;
|
|
|
+ }
|
|
|
+ method = klass ? klass.fn.prototype[selector] : receiver.klass && receiver[selector];
|
|
|
+ if(method) {
|
|
|
+ return method.apply(receiver, args);
|
|
|
+ } else {
|
|
|
+ return messageNotUnderstood(receiver, selector, args);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ /* Handles #dnu: *and* JavaScript method calls.
|
|
|
+ if the receiver has no klass, we consider it a JS object (outside of the
|
|
|
+ Amber system). Else assume that the receiver understands #doesNotUnderstand: */
|
|
|
+
|
|
|
+ function messageNotUnderstood(receiver, selector, args) {
|
|
|
+ /* Handles JS method calls. */
|
|
|
+ if(receiver.klass === undefined || receiver.allowJavaScriptCalls) {
|
|
|
+ return callJavaScriptMethod(receiver, selector, args);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Handles not understood messages. Also see the Amber counter-part
|
|
|
+ Object>>doesNotUnderstand: */
|
|
|
+
|
|
|
+ return receiver._doesNotUnderstand_(
|
|
|
+ st.Message._new()
|
|
|
+ ._selector_(st.convertSelector(selector))
|
|
|
+ ._arguments_(args)
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Call a method of a JS object, or answer a property if it exists.
|
|
|
+ Else try wrapping a JSObjectProxy around the receiver.
|
|
|
+
|
|
|
+ If the object property is a function, then call it, except if it starts with
|
|
|
+ an uppercase character (we probably want to answer the function itself in this
|
|
|
+ case and send it #new from Amber).
|
|
|
+
|
|
|
+ Converts keyword-based selectors by using the first
|
|
|
+ keyword only, but keeping all message arguments.
|
|
|
+
|
|
|
+ Example:
|
|
|
+ "self do: aBlock with: anObject" -> "self.do(aBlock, anObject)" */
|
|
|
+
|
|
|
+ function callJavaScriptMethod(receiver, selector, args) {
|
|
|
+ var jsSelector = selector._asJavaScriptSelector();
|
|
|
+ var jsProperty = receiver[jsSelector];
|
|
|
+ if(typeof jsProperty === "function" && !/^[A-Z]/.test(jsSelector)) {
|
|
|
+ return jsProperty.apply(receiver, args);
|
|
|
+ } else if(jsProperty !== undefined) {
|
|
|
+ if(args[0]) {
|
|
|
+ receiver[jsSelector] = args[0];
|
|
|
+ return nil;
|
|
|
+ } else {
|
|
|
+ return jsProperty;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return st.send(st.JSObjectProxy._on_(receiver), selector, args);
|
|
|
+ }
|
|
|
+
|
|
|
+ this.messageNotUnderstood = messageNotUnderstood;
|
|
|
+}
|
|
|
+
|
|
|
function SelectorConversionBrik(brikz, st) {
|
|
|
/* Convert a Smalltalk selector into a JS selector */
|
|
|
|
|
@@ -872,6 +881,8 @@ inherits(SmalltalkMethodContext, SmalltalkObject);
|
|
|
var api = new Smalltalk;
|
|
|
var brikz = new Brikz(api);
|
|
|
|
|
|
+brikz.dnu = DNUBrik;
|
|
|
+brikz.messageSend = MessageSendBrik;
|
|
|
brikz.organize = OrganizeBrik;
|
|
|
brikz.selectorConversion = SelectorConversionBrik;
|
|
|
brikz.smalltalk = SmalltalkFactory;
|