'coffee_sources': [
'browser/api/lib/atom.coffee',
'browser/api/lib/ipc.coffee',
+ 'browser/api/lib/.coffee',
'browser/api/lib/window.coffee',
'browser/atom/atom.coffee',
+ 'browser/atom/objects_registry.coffee',
+ 'browser/atom/rpc_server.coffee',
'renderer/api/lib/ipc.coffee',
+ 'renderer/api/lib/remote.coffee',
],
'lib_sources': [
'app/atom_main_delegate.cc',
Window = process.atom_binding('window').Window
Window.prototype.__proto__ = EventEmitter.prototype
-# Convient accessors.
-setupGetterAndSetter = (constructor, name, getter, setter) ->
- if getter?
- constructor.prototype.__defineGetter__ name, ->
- this[getter].apply(this, arguments)
- if setter?
- constructor.prototype.__defineSetter__ name, ->
- this[setter].apply(this, arguments)
-
-setupGetterAndSetter Window, 'fullscreen', 'isFullscreen', 'setFullscreen'
-setupGetterAndSetter Window, 'size', 'getSize', 'setSize'
-setupGetterAndSetter Window, 'maximumSize', 'getMaximumSize', 'setMaximumSize'
-setupGetterAndSetter Window, 'minimumSize', 'getMinimumSize', 'setMinimumSize'
-setupGetterAndSetter Window, 'resizable', 'isResizable', 'setResizable'
-setupGetterAndSetter Window, 'alwaysOnTop', 'isAlwaysOnTop', 'setAlwaysOnTop'
-setupGetterAndSetter Window, 'position', 'getPosition', 'setPosition'
-setupGetterAndSetter Window, 'title', 'getTitle', 'setTitle'
-setupGetterAndSetter Window, 'kiosk', 'isKiosk', 'setKiosk'
-setupGetterAndSetter Window, 'url', 'getURL', 'loadURL'
-
module.exports = Window
global.__atom = atom
# Add Atom.app/Contents/Resources/browser/api/lib to require's search paths,
-# which contains javascript of Atom's built-in libraries.
-require('module').globalPaths.push path.join(__dirname, '..', 'api', 'lib')
+# which contains javascript part of Atom's built-in libraries.
+globalPaths = require('module').globalPaths
+globalPaths.push path.join(__dirname, '..', 'api', 'lib')
+
+# And Atom.app/Contents/Resources/common/api/lib
+globalPaths.push path.join(__dirname, '..', '..', 'common', 'api', 'lib')
# Don't quit on fatal error.
process.on 'uncaughtException', (error) ->
console.error 'uncaughtException:'
console.error message
+# Load the RPC server.
+require './rpc_server.js'
+
# Now we try to load app's package.json.
packageJson = null
--- /dev/null
+module.exports =
+class ObjectsRegistry
+ @nextId = 0
+
+ constructor: ->
+ @objects = []
+
+ getNextId: ->
+ ++ObjectsRegistry.nextId
+
+ add: (obj) ->
+ id = @getNextId()
+ @objects[id] = obj
+ id
+
+ remove: (id) ->
+ obj = @objects[id]
+ delete @objects[id]
+ obj
+
+ get: (id) ->
+ @objects[id]
--- /dev/null
+ipc = require 'ipc'
+path = require 'path'
+ObjectsRegistry = require './objects_registry.js'
+
+objectsRegistry = new ObjectsRegistry
+
+class PlainObject
+ constructor: (value) ->
+ @type = typeof value
+ @type = 'value' if value is null
+
+ if @type is 'object' or @type is 'function'
+ @name = value.constructor.name
+ @id = objectsRegistry.add value
+
+ @members = []
+ for prop, field of value
+ @members.push { name: prop, type: typeof field }
+ else
+ @type = 'value'
+ @value = value
+
+ipc.on 'ATOM_INTERNAL_REQUIRE', (event, process_id, routing_id, module) ->
+ event.result = new PlainObject(require(module))
+
+ipc.on 'ATOM_INTERNAL_CONSTRUCTOR', (event, process_id, routing_id, id, args) ->
+ try
+ # Call new with array of arguments.
+ # TODO(zcbenz): Paste the URL of the StackOverflow question.
+ constructor = objectsRegistry.get id
+ obj = new (Function::bind.apply(constructor, [null].concat(args)))
+ event.result = new PlainObject(obj)
+ catch e
+ event.result = type: 'error', value: e.message
+
+ipc.on 'ATOM_INTERNAL_FUNCTION_CALL', (event, process_id, routing_id, id, args) ->
+ try
+ ret = objectsRegistry.get(id).apply global, args
+ event.result = new PlainObject(ret)
+ catch e
+ event.result = type: 'error', value: e.message
+
+ipc.on 'ATOM_INTERNAL_MEMBER_CALL', (event, process_id, routing_id, id, method, args) ->
+ try
+ obj = objectsRegistry.get id
+ ret = obj[method].apply(obj, args)
+ event.result = new PlainObject(ret)
+ catch e
+ event.result = type: 'error', value: e.message
+
+ipc.on 'ATOM_INTERNAL_MEMBER_SET', (event, process_id, routing_id, id, name, value) ->
+ try
+ objectsRegistry.get(id)[name] = value
+ catch e
+ event.result = type: 'error', value: e.message
+
+ipc.on 'ATOM_INTERNAL_MEMBER_GET', (event, process_id, routing_id, id, name) ->
+ try
+ event.result = new PlainObject(objectsRegistry.get(id)[name])
+ catch e
+ event.result = type: 'error', value: e.message
atom.browserMainParts.preMainMessageLoopRun = function() {
mainWindow = new Window({ width: 800, height: 600 });
- mainWindow.url = 'file://' + __dirname + '/index.html';
+ mainWindow.loadURL('file://' + __dirname + '/index.html');
mainWindow.on('page-title-updated', function(event, title) {
event.preventDefault();
- this.title = 'Atom Shell - ' + title;
+ this.setTitle('Atom Shell - ' + title);
});
}
--- /dev/null
+ipc = require 'ipc'
+
+generateFromPainObject = (plain) ->
+ if plain.type is 'value'
+ return plain.value
+ else if plain.type is 'error'
+ throw new Error('Remote Error: ' + plain.value)
+ else
+ # A shadow class to represent the remote object.
+ class RemoteObject
+ constructor: () ->
+ if @constructor == RemoteObject
+ # Constructor call.
+ obj = ipc.sendChannelSync 'ATOM_INTERNAL_CONSTRUCTOR', plain.id, Array::slice.call(arguments)
+ # Returning object in constructor will replace constructed object
+ # with returned object.
+ return generateFromPainObject obj
+ else
+ # Function call.
+ ret = ipc.sendChannelSync 'ATOM_INTERNAL_FUNCTION_CALL', plain.id, Array::slice.call(arguments)
+ generateFromPainObject ret
+
+ # Polulate shadow members.
+ for member in plain.members
+ do (member) ->
+ if member.type is 'function'
+ RemoteObject[member.name] = ->
+ # Call member function.
+ ret = ipc.sendChannelSync 'ATOM_INTERNAL_MEMBER_CALL', plain.id, member.name, Array::slice.call(arguments)
+ generateFromPainObject ret
+ else
+ RemoteObject.__defineSetter__ member.name, (value) ->
+ # Set member data.
+ ipc.sendChannelSync 'ATOM_INTERNAL_MEMBER_SET', plain.id, member.name, value
+ undefined
+
+ RemoteObject.__defineGetter__ member.name, ->
+ # Get member data.
+ ret = ipc.sendChannelSync 'ATOM_INTERNAL_MEMBER_GET', plain.id, member.name
+ generateFromPainObject ret
+
+ RemoteObject
+
+exports.require = (module) ->
+ plain = ipc.sendChannelSync 'ATOM_INTERNAL_REQUIRE', module
+ generateFromPainObject plain
-Subproject commit 027d18bde8c24534215095aadceb78e7a61b2b5c
+Subproject commit 5c651db8ff28c710bedecd0599ce8a1249ae843f