{"action":"created","comment":{"url":"https://api.github.com/repos/livecode/livecode/pulls/comments/50892757","id":50892757,"diff_hunk":"@@ -0,0 +1,240 @@\n+# Signals and Events for LiveCode Builder Widgets\n+Copyright © LiveCode Ltd.\n+\n+## Introduction\n+\n+The types of external occurrences that a LiveCode Builder (LCB) widget can respond to can be broadly divided into two categories:\n+\n+1. **Signals**: these are emitted from a specific LCB widget, and are handled only by those widgets that are already expecting to receive them.\n+\n+   For example, the _Segmented_ widget emits a \"segmentSelected\" message when a segment is selected.  If the _Segmented_ widget was a child of a composed widget, then _only_ the composed widget receives the message, and only if the widget code contains a public \"OnSegmentSelected\" handler (i.e. it is expecting to receive the message).\n+\n+2. **Events**: these originate from outside the program, and represent some sort of interaction with the outside world (for example, a mouse movement or keyboard event).  They are targeted at a specific widget (based on diverse criteria, such as position, visibility, or various types of focus), and propagate based on widget composition.\n+\n+This document describes a new, more rigorous scheme for ensuring that these behave in a unambiguous and consistent way, and that there are good facilities for LCB programmers to make use of them.\n+\n+## Existing problems\n+\n+There are several issues with the way signals and events currently work for controls implemented in LCB.  The problems affect both the way that widgets can be used to construct other widgets (i.e. composed widgets), and the easy of handling widgets alongside legacy controls from a LiveCode Script (LCS) point of view.\n+\n+1. Signal emission and handling is not very well checked.  At a language level, there is no way for widgets to describe what type of signals they can emit.  Similarly, there is no syntax for distinguishing between widget handlers and \"normal\" handlers, meaning that (in principle) a handler that is not intended to be a signal handler could end up getting called in a signal context if a child widget happens to start emitting a signal with a matching name.  Finally, there is no facility for checking that signal prototypes match signal handler prototypes.\n+\n+2. Similar issues to 1. above apply for event handling.\n+\n+3. In LCS, event handling propagates upward: if a button doesn't have an `MouseUp` handler, then the event gets passed on to a parent card, and so on.  Furthermore, there is the idea of explicit propagation: it is possible to do something in an event handler and then, for example, `pass MouseUp` to invoke the normal event propagation logic.\n+\n+   In LCB, event propagation is *not* currently automatic.  If a widget does not explicitly handle and re-`post` each possible event, then its script (or parent widget) never sees the event.\n+\n+4. Sometimes, it's important to be able to be able to prevent child widgets from seeing an event, or performing some pre-processing / post-processing around the normal event handling process.  The current LCB event handling scheme does not permit this.\n+\n+## Assumptions\n+\n+For the purposes of this document we assume that:\n+\n+* All connection of signal and event handlers is implicit, rather than explicit.\n+\n+* An instance of a widget as an engine control can be considered as a composed widget, comprising a script and the \"real\" widget instance (this makes sense when you consider the fact that the widget control exists, has a script, and can be manipulated even if the \"real\" widget was unable to be loaded for some reason).  This will be referred to as a \"host widget\" in the rest of this document.\n+\n+## Signals\n+\n+### Signal definitions\n+\n+A LiveCode module may include signal type definitions in its top-level scope [1-2]:\n+\n+    public signal type <name:id>(<params:formals>)\n+\n+If the module is imported by another module via the `use` syntax, the signal definitions are made available in the same way as a variable, handler or type definition.\n+\n+**Notes**:\n+\n+1. These definitions provide a convenient anchor point for documentation comments about the purpose and usage of a signal.\n+\n+2. It would be helpful to provide a `com.livecode.signals` module in the standard library that provides definitions of \"standard\" signals and descriptions of the recommended way to use them.  Examples of standard signals might include `Clicked`, `SelectionChanged`, etc.\n+\n+### Signal emission\n+\n+Signals are explicitly emitted by a widget using an `emit` statement:\n+\n+    emit <name:id>(<params:expressions>)\n+\n+It is a run-time error to emit a signal with the wrong number or types of emission parameters [1].  The compiler may statically verify that signals are emitted with compatible parameter lists.\n+\n+The `emit` statement may return before all the signal handlers for the signal have finished running [2].\n+\n+The signal handlers for a signal get run exactly once for each emission.  All of the handlers for an emission must complete before any of the handlers for a subsequent emission begin [3].\n+\n+The signal handlers for a signal may be run in any order.\n+\n+The `emit` statement does not return a value [4].\n+\n+**Notes**:\n+\n+1. In principle a widget could set properties on itself before emitting a signal.  However, when adding features to LCS previously it's been found that users prefer relevant information to be passed as parameters to messages rather than out-of-band.  Passing parameters to signal emission also helps to ensure that all of the correct setup has been performed for signal handling - for example, if a parameter is added or removed from the signal, it's easy to verify that all relevant code has been updated.\n+\n+2. Although, initially, signal emission _could_ be implemented by iterating over registered signal handlers and calling them within the execution of the `emit` statement, this could easily lead to arbitrarily-deep signal emission chains going backwards and forwards between LCS and LCB contexts.  By allowing signal emission to be delayed, this is avoided (the current stack can be allowed to unwind before signal dispatch is performed).  Delaying signal handling also helps to reason about the safety of deleting a widget in response to receiving a signal from it.\n+\n+3. Emitting a signal twice from the same handler - even with the same parameters - will cause all of the handlers for that signal to be run twice.\n+\n+4. This is a consequence of asynchronous signal handling.\n+\n+### Signal handling\n+\n+Signal handlers are explicitly declared in an LCB program using a `signal handler` declaration [1]:\n+\n+    signal handler for <name:id> is <handler:constexpr>\n+\n+At most one signal handler for each distinct signal may be declared.  The **handler** must conform to the signal's prototype.\n+\n+Signal handlers have no return value.\n+\n+Within the body of a signal handler, `the signal source` evaluates to the widget that emitted the signal that is being handled.\n+\n+It is an error to evaluate `the signal source` outside a signal handling context.\n+\n+**Notes:**\n+\n+1. Explicitly connecting signals to handlers is helpful because it allows:\n+\n+   * Using a single handler for multiple signals with the same formals\n+   * Handling multiple signals with the same name but different formals (it would be necessary to use a fully-qualified signal **name** when doing this)\n+\n+### Signal connection\n+\n+When a child widget is added to a composed widget, the composed widget is connected to receive signals from the child.  If a signal is emitted by the child widget, the corresponding handler (if any) is run in the composed widget.\n+\n+When a child widget is removed from a composed widget, the composed widget is disconnected from the child widget's signals.\n+\n+**Notes:**\n+\n+1. When these rules are applied to \"host widgets\", each public script `on` handler in the host widget's script is automatically considered to have been declared as a polymorphic signal handler for all signals with a matching name.  For example, an `on Clicked` handler in a host widget's script would handler both `com.livecode.signals.Clicked` and `org.example.signals.Clicked` signals.\n+\n+## Events\n+\n+### Event declarations\n+\n+A LiveCode module may include event declarations in its top-level scope [1]:\n+\n+    public event type <name:id>\n+\n+**Notes:**\n+\n+1. It would be necessary to provide a `com.livecode.events` module that includes event type definitions for all of the engine events.  With the events API described in this document, it wouldn't really be useful for other modules to declare new event types because only the engine can enqueue events.\n+\n+### Event processing\n+\n+Events are processed in three phases [1]:\n+\n+1. **Enter**: before handling an event, perform event-handling setup tasks and determine at point in the event hierarchy the event should be targeted\n+\n+2. **Dispatch**: do work in response to the event\n+\n+3. **Leave**: perform any tasks that should be carried out after event handling (for example, tearing down any state set up during event enter)\n+\n+Events are processed synchronously.  If an event is submitted to the event manager while another event is being processed, that event will be queued.\n+\n+Before beginning to process an event, the event manager first determines which control should be the **target** of the event (taking into account visibilities, and bounding rectangles) [2].  A list of \"interested controls\" is built.  This recursively contains every parent of the target.  This is used to determine which objects should have their event handlers run.\n+\n+**Notes:**\n+\n+1. The enter phase and leave phase facilitate the implementation of behaviour that wraps normal event dispatch.  For example, consider a composed widget with a border that highlights when the mouse is inside it.  To ensure that highlight changes sequence correctly with with its child widgets, the highlight must be enabled during the `MouseEnter` event's enter phase, and hidden during the `MouseLeave` event's leave phase.\n+\n+2. How the target of an event is determined may vary a lot on a per-event-type basis (for example, the target for a mouse click will depend on the mouse position, but the target for a keyboard event may depend on the keyboard focus).  For the purposes of this document, assume that it is an arbitrary process.\n+\n+### Event data\n+\n+When an event is submitted to the event manager, it has a **event type** and a set of **event data**.  The event data is a datastructure containing all of the captured data relating to the event itself [1-2].\n+\n+The `the event target` expression evaluates to the event's target control [3-4].\n+\n+**Notes:**\n+\n+1. For example, when creating a mouse event, it is important to capture the position of the mouse at the time the event began to be dispatched into the event data.  If computationally-intensive event handlers are run, the user could move the mouse between event creation and event handling.\n+\n+2. Various syntax related to event parameters (such as `the mouse position`) should probably refer to the event data of the latest event processed.\n+\n+3. It might be useful to provide `the event target is me` (or equivalent syntax) to test whether an event is targeted at the handling control or one of its children.\n+\n+4. If `the event target` is a widget, then `the target` LCS expression evaluates to the corresponding host widget.\n+\n+\n+### Event handlers\n+\n+All event handlers (for enter, dispatch and leave phases) must conform to:\n+\n+    public type EventHandler() returns any\n+\n+The return value of all event handlers is discarded.\n+\n+If an event handler includes a statement that \"blocks\", i.e. pauses script execution while preventing events from being handled, it prevents all further event handling until it completes (although new events may be enqueued) [1].\n+\n+If an event handler includes a statement that \"yields\", i.e. pauses script execution while permitting events to be handled, it \"detaches\" from event processing (i.e. event processing will move on to subsequent handlers for the current event while the script is paused) [2].\n+\n+**Notes:**\n+\n+1. This approximates the effect of `wait` statements and `url` expressions in LCS.  In these cases, the user expects nothing to happen until the expected operation completes, which precludes continuing to handle events.\n+\n+2. This approximates the effect of `wait with messages` statements in LCS.  `wait with messages` implies that events should continue to be handled while the script that calls it is paused, which includes event handling.  However, only one event can be being processed at a time.  A good way to reconcile these two requirements is to make the event manager treat an event handler that yields as if it had returned.\n+\n+### Enter phase\n+\n+During the enter phase, **pre-event** handlers are run.  They are run from \"outside-in\"; a parent widget's pre-event handler runs before the pre-event handler of its child widgets.\n+\n+A pre-event handler is declared using a `pre event handler` declaration:\n+\n+    pre event handler for <name:id> is <handler:constexpr>\n+\n+By default, all pre-event handlers declared by the list of interested controls are run.  There is no need to \"pass\" the event onwards [1].\n+\n+A control can use the pre-event handler to **capture** an event:\n+\n+    capture event\n+\n+The `capture event` statement makes the capturing control becomes the \"target\" for the event; all its children are removed from the list of interested controls [2,3].\n+\n+**Notes:**\n+\n+1. As per the `mouseEnter`/`mouseLeave`, implicit passing reflects the expectation that pre- and post-event handlers are usually be used to implement behaviour that complements rather than conflicts with that of other interested controls.\n+\n+2. This allows composed widgets to \"hide\" events from their children.\n+\n+3. Since `capture event` causes the capturing control to become the target, the capturing control can't do anything that requires knowledge of the \"original\" target in its on-event handler unless it saves `the event target` in the pre-event handler before `capture event`.  On the other hand, there's not much point in having separate pre-event and on-event handlers when capturing because they're guaranteed to be run immediately one after another.\n+\n+### Dispatch phase\n+\n+During the dispatch phase, **on-event** handlers are run.  They are run from \"inside-out\", starting from the target control.  A parent widget's on-event handler runs after its child widgets' on-event handlers.\n+\n+An on-event handler is declared using an `event handler` declaration [1]:\n+\n+    [on] event handler for <name:id> is <handler:constexpr>\n+\n+By default, if an on-event handler is found for an event, then it **blocks** further on-event handler execution for the event [2].\n+\n+An on-event handler can use the `pass event` statement to prevent the default-blocking behaviour.\n+\n+The `pass event` statement does not return.\n+\n+If an on-event handler yields, it is treated as having blocked further on-event handler execution.  It is an error to `pass event` after yielding [3].\n+\n+**Notes:**\n+\n+1. Since most widgets will only need to handle events during the dispatch phase, on-event handlers may be declared without a qualifier.\n+\n+2. This is for conceptual compatibility with LCS.\n+\n+3. Since yielding detaches an event handler from event processing, there is subsequently no \"next handler\" for the on-event handler to pass the event on to.\n+\n+### Leave phase\n+\n+During the leave phase, **post-event** handlers are run.  Like on-event handlers, they are run from \"inside-out\", starting from the target control.\n+\n+All interested controls have the opportunity to run a post-event handler, even if an on-event handler blocked the event during the dispatch phase [1].\n+\n+A post-event handler is declared using a `post event handler` declaration:\n+\n+    post event handler for <name:id> is <handler:constexpr>\n+","path":"docs/specs/lcb-signals-and-events.md","position":235,"original_position":235,"commit_id":"6d22358edb4e13b6dda827283eb30d0bb6d2f723","original_commit_id":"6d22358edb4e13b6dda827283eb30d0bb6d2f723","user":{"login":"montegoulding","id":351144,"avatar_url":"https://avatars.githubusercontent.com/u/351144?v=3","gravatar_id":"","url":"https://api.github.com/users/montegoulding","html_url":"https://github.com/montegoulding","followers_url":"https://api.github.com/users/montegoulding/followers","following_url":"https://api.github.com/users/montegoulding/following{/other_user}","gists_url":"https://api.github.com/users/montegoulding/gists{/gist_id}","starred_url":"https://api.github.com/users/montegoulding/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/montegoulding/subscriptions","organizations_url":"https://api.github.com/users/montegoulding/orgs","repos_url":"https://api.github.com/users/montegoulding/repos","events_url":"https://api.github.com/users/montegoulding/events{/privacy}","received_events_url":"https://api.github.com/users/montegoulding/received_events","type":"User","site_admin":false},"body":"@peter-b I see what you mean about the event order.","created_at":"2016-01-26T20:11:09Z","updated_at":"2016-01-26T20:11:09Z","html_url":"https://github.com/livecode/livecode/pull/3495#discussion_r50892757","pull_request_url":"https://api.github.com/repos/livecode/livecode/pulls/3495","_links":{"self":{"href":"https://api.github.com/repos/livecode/livecode/pulls/comments/50892757"},"html":{"href":"https://github.com/livecode/livecode/pull/3495#discussion_r50892757"},"pull_request":{"href":"https://api.github.com/repos/livecode/livecode/pulls/3495"}}},"pull_request":{"url":"https://api.github.com/repos/livecode/livecode/pulls/3495","id":56755045,"html_url":"https://github.com/livecode/livecode/pull/3495","diff_url":"https://github.com/livecode/livecode/pull/3495.diff","patch_url":"https://github.com/livecode/livecode/pull/3495.patch","issue_url":"https://api.github.com/repos/livecode/livecode/issues/3495","number":3495,"state":"open","locked":false,"title":"docs: Add specification for LCB widget signals and events.","user":{"login":"peter-b","id":47528,"avatar_url":"https://avatars.githubusercontent.com/u/47528?v=3","gravatar_id":"","url":"https://api.github.com/users/peter-b","html_url":"https://github.com/peter-b","followers_url":"https://api.github.com/users/peter-b/followers","following_url":"https://api.github.com/users/peter-b/following{/other_user}","gists_url":"https://api.github.com/users/peter-b/gists{/gist_id}","starred_url":"https://api.github.com/users/peter-b/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/peter-b/subscriptions","organizations_url":"https://api.github.com/users/peter-b/orgs","repos_url":"https://api.github.com/users/peter-b/repos","events_url":"https://api.github.com/users/peter-b/events{/privacy}","received_events_url":"https://api.github.com/users/peter-b/received_events","type":"User","site_admin":false},"body":"Initial draft of specification for revised LiveCode Builder signal and event subsystem.\r\n\r\n[Rendered version](https://github.com/peter-b/livecode/blob/feature/lcb-signals-and-events/docs/specs/lcb-signals-and-events.md)\r\n\r\n**Unresolved issues:**\r\n* [x] What happens when an event handler blocks/waits in the \"dispatch\" phase (possibly indefinitely)?\r\n* [x] Relationship with LCS `before` and `after` handlers\r\n* [ ] More / better examples","created_at":"2016-01-21T14:21:03Z","updated_at":"2016-01-26T20:11:09Z","closed_at":null,"merged_at":null,"merge_commit_sha":"68893364d9022e5c07e07bb967bbe31d1ed53741","assignee":null,"milestone":{"url":"https://api.github.com/repos/livecode/livecode/milestones/83","html_url":"https://github.com/livecode/livecode/milestones/8.0.0-rc-1","labels_url":"https://api.github.com/repos/livecode/livecode/milestones/83/labels","id":1407237,"number":83,"title":"8.0.0-rc-1","description":null,"creator":{"login":"peter-b","id":47528,"avatar_url":"https://avatars.githubusercontent.com/u/47528?v=3","gravatar_id":"","url":"https://api.github.com/users/peter-b","html_url":"https://github.com/peter-b","followers_url":"https://api.github.com/users/peter-b/followers","following_url":"https://api.github.com/users/peter-b/following{/other_user}","gists_url":"https://api.github.com/users/peter-b/gists{/gist_id}","starred_url":"https://api.github.com/users/peter-b/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/peter-b/subscriptions","organizations_url":"https://api.github.com/users/peter-b/orgs","repos_url":"https://api.github.com/users/peter-b/repos","events_url":"https://api.github.com/users/peter-b/events{/privacy}","received_events_url":"https://api.github.com/users/peter-b/received_events","type":"User","site_admin":false},"open_issues":9,"closed_issues":3,"state":"open","created_at":"2015-11-11T19:38:29Z","updated_at":"2016-01-26T17:01:20Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/livecode/livecode/pulls/3495/commits","review_comments_url":"https://api.github.com/repos/livecode/livecode/pulls/3495/comments","review_comment_url":"https://api.github.com/repos/livecode/livecode/pulls/comments{/number}","comments_url":"https://api.github.com/repos/livecode/livecode/issues/3495/comments","statuses_url":"https://api.github.com/repos/livecode/livecode/statuses/6d22358edb4e13b6dda827283eb30d0bb6d2f723","head":{"label":"peter-b:feature/lcb-signals-and-events","ref":"feature/lcb-signals-and-events","sha":"6d22358edb4e13b6dda827283eb30d0bb6d2f723","user":{"login":"peter-b","id":47528,"avatar_url":"https://avatars.githubusercontent.com/u/47528?v=3","gravatar_id":"","url":"https://api.github.com/users/peter-b","html_url":"https://github.com/peter-b","followers_url":"https://api.github.com/users/peter-b/followers","following_url":"https://api.github.com/users/peter-b/following{/other_user}","gists_url":"https://api.github.com/users/peter-b/gists{/gist_id}","starred_url":"https://api.github.com/users/peter-b/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/peter-b/subscriptions","organizations_url":"https://api.github.com/users/peter-b/orgs","repos_url":"https://api.github.com/users/peter-b/repos","events_url":"https://api.github.com/users/peter-b/events{/privacy}","received_events_url":"https://api.github.com/users/peter-b/received_events","type":"User","site_admin":false},"repo":{"id":24674939,"name":"livecode","full_name":"peter-b/livecode","owner":{"login":"peter-b","id":47528,"avatar_url":"https://avatars.githubusercontent.com/u/47528?v=3","gravatar_id":"","url":"https://api.github.com/users/peter-b","html_url":"https://github.com/peter-b","followers_url":"https://api.github.com/users/peter-b/followers","following_url":"https://api.github.com/users/peter-b/following{/other_user}","gists_url":"https://api.github.com/users/peter-b/gists{/gist_id}","starred_url":"https://api.github.com/users/peter-b/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/peter-b/subscriptions","organizations_url":"https://api.github.com/users/peter-b/orgs","repos_url":"https://api.github.com/users/peter-b/repos","events_url":"https://api.github.com/users/peter-b/events{/privacy}","received_events_url":"https://api.github.com/users/peter-b/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/peter-b/livecode","description":"Peter Brett's LiveCode development repository","fork":true,"url":"https://api.github.com/repos/peter-b/livecode","forks_url":"https://api.github.com/repos/peter-b/livecode/forks","keys_url":"https://api.github.com/repos/peter-b/livecode/keys{/key_id}","collaborators_url":"https://api.github.com/repos/peter-b/livecode/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/peter-b/livecode/teams","hooks_url":"https://api.github.com/repos/peter-b/livecode/hooks","issue_events_url":"https://api.github.com/repos/peter-b/livecode/issues/events{/number}","events_url":"https://api.github.com/repos/peter-b/livecode/events","assignees_url":"https://api.github.com/repos/peter-b/livecode/assignees{/user}","branches_url":"https://api.github.com/repos/peter-b/livecode/branches{/branch}","tags_url":"https://api.github.com/repos/peter-b/livecode/tags","blobs_url":"https://api.github.com/repos/peter-b/livecode/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/peter-b/livecode/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/peter-b/livecode/git/refs{/sha}","trees_url":"https://api.github.com/repos/peter-b/livecode/git/trees{/sha}","statuses_url":"https://api.github.com/repos/peter-b/livecode/statuses/{sha}","languages_url":"https://api.github.com/repos/peter-b/livecode/languages","stargazers_url":"https://api.github.com/repos/peter-b/livecode/stargazers","contributors_url":"https://api.github.com/repos/peter-b/livecode/contributors","subscribers_url":"https://api.github.com/repos/peter-b/livecode/subscribers","subscription_url":"https://api.github.com/repos/peter-b/livecode/subscription","commits_url":"https://api.github.com/repos/peter-b/livecode/commits{/sha}","git_commits_url":"https://api.github.com/repos/peter-b/livecode/git/commits{/sha}","comments_url":"https://api.github.com/repos/peter-b/livecode/comments{/number}","issue_comment_url":"https://api.github.com/repos/peter-b/livecode/issues/comments{/number}","contents_url":"https://api.github.com/repos/peter-b/livecode/contents/{+path}","compare_url":"https://api.github.com/repos/peter-b/livecode/compare/{base}...{head}","merges_url":"https://api.github.com/repos/peter-b/livecode/merges","archive_url":"https://api.github.com/repos/peter-b/livecode/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/peter-b/livecode/downloads","issues_url":"https://api.github.com/repos/peter-b/livecode/issues{/number}","pulls_url":"https://api.github.com/repos/peter-b/livecode/pulls{/number}","milestones_url":"https://api.github.com/repos/peter-b/livecode/milestones{/number}","notifications_url":"https://api.github.com/repos/peter-b/livecode/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/peter-b/livecode/labels{/name}","releases_url":"https://api.github.com/repos/peter-b/livecode/releases{/id}","deployments_url":"https://api.github.com/repos/peter-b/livecode/deployments","created_at":"2014-10-01T10:49:08Z","updated_at":"2015-03-05T08:56:34Z","pushed_at":"2016-01-26T10:40:28Z","git_url":"git://github.com/peter-b/livecode.git","ssh_url":"git@github.com:peter-b/livecode.git","clone_url":"https://github.com/peter-b/livecode.git","svn_url":"https://github.com/peter-b/livecode","homepage":"http://www.livecode.com/","size":102517,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"develop"}},"base":{"label":"livecode:develop","ref":"develop","sha":"6fcb626fee2574c16ed01451bd78bc8f6886f002","user":{"login":"livecode","id":3985749,"avatar_url":"https://avatars.githubusercontent.com/u/3985749?v=3","gravatar_id":"","url":"https://api.github.com/users/livecode","html_url":"https://github.com/livecode","followers_url":"https://api.github.com/users/livecode/followers","following_url":"https://api.github.com/users/livecode/following{/other_user}","gists_url":"https://api.github.com/users/livecode/gists{/gist_id}","starred_url":"https://api.github.com/users/livecode/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/livecode/subscriptions","organizations_url":"https://api.github.com/users/livecode/orgs","repos_url":"https://api.github.com/users/livecode/repos","events_url":"https://api.github.com/users/livecode/events{/privacy}","received_events_url":"https://api.github.com/users/livecode/received_events","type":"Organization","site_admin":false},"repo":{"id":9334445,"name":"livecode","full_name":"livecode/livecode","owner":{"login":"livecode","id":3985749,"avatar_url":"https://avatars.githubusercontent.com/u/3985749?v=3","gravatar_id":"","url":"https://api.github.com/users/livecode","html_url":"https://github.com/livecode","followers_url":"https://api.github.com/users/livecode/followers","following_url":"https://api.github.com/users/livecode/following{/other_user}","gists_url":"https://api.github.com/users/livecode/gists{/gist_id}","starred_url":"https://api.github.com/users/livecode/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/livecode/subscriptions","organizations_url":"https://api.github.com/users/livecode/orgs","repos_url":"https://api.github.com/users/livecode/repos","events_url":"https://api.github.com/users/livecode/events{/privacy}","received_events_url":"https://api.github.com/users/livecode/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/livecode/livecode","description":"","fork":false,"url":"https://api.github.com/repos/livecode/livecode","forks_url":"https://api.github.com/repos/livecode/livecode/forks","keys_url":"https://api.github.com/repos/livecode/livecode/keys{/key_id}","collaborators_url":"https://api.github.com/repos/livecode/livecode/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/livecode/livecode/teams","hooks_url":"https://api.github.com/repos/livecode/livecode/hooks","issue_events_url":"https://api.github.com/repos/livecode/livecode/issues/events{/number}","events_url":"https://api.github.com/repos/livecode/livecode/events","assignees_url":"https://api.github.com/repos/livecode/livecode/assignees{/user}","branches_url":"https://api.github.com/repos/livecode/livecode/branches{/branch}","tags_url":"https://api.github.com/repos/livecode/livecode/tags","blobs_url":"https://api.github.com/repos/livecode/livecode/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/livecode/livecode/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/livecode/livecode/git/refs{/sha}","trees_url":"https://api.github.com/repos/livecode/livecode/git/trees{/sha}","statuses_url":"https://api.github.com/repos/livecode/livecode/statuses/{sha}","languages_url":"https://api.github.com/repos/livecode/livecode/languages","stargazers_url":"https://api.github.com/repos/livecode/livecode/stargazers","contributors_url":"https://api.github.com/repos/livecode/livecode/contributors","subscribers_url":"https://api.github.com/repos/livecode/livecode/subscribers","subscription_url":"https://api.github.com/repos/livecode/livecode/subscription","commits_url":"https://api.github.com/repos/livecode/livecode/commits{/sha}","git_commits_url":"https://api.github.com/repos/livecode/livecode/git/commits{/sha}","comments_url":"https://api.github.com/repos/livecode/livecode/comments{/number}","issue_comment_url":"https://api.github.com/repos/livecode/livecode/issues/comments{/number}","contents_url":"https://api.github.com/repos/livecode/livecode/contents/{+path}","compare_url":"https://api.github.com/repos/livecode/livecode/compare/{base}...{head}","merges_url":"https://api.github.com/repos/livecode/livecode/merges","archive_url":"https://api.github.com/repos/livecode/livecode/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/livecode/livecode/downloads","issues_url":"https://api.github.com/repos/livecode/livecode/issues{/number}","pulls_url":"https://api.github.com/repos/livecode/livecode/pulls{/number}","milestones_url":"https://api.github.com/repos/livecode/livecode/milestones{/number}","notifications_url":"https://api.github.com/repos/livecode/livecode/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/livecode/livecode/labels{/name}","releases_url":"https://api.github.com/repos/livecode/livecode/releases{/id}","deployments_url":"https://api.github.com/repos/livecode/livecode/deployments","created_at":"2013-04-10T00:15:57Z","updated_at":"2016-01-24T04:49:28Z","pushed_at":"2016-01-26T17:25:52Z","git_url":"git://github.com/livecode/livecode.git","ssh_url":"git@github.com:livecode/livecode.git","clone_url":"https://github.com/livecode/livecode.git","svn_url":"https://github.com/livecode/livecode","homepage":null,"size":134726,"stargazers_count":107,"watchers_count":107,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":88,"mirror_url":null,"open_issues_count":51,"forks":88,"open_issues":51,"watchers":107,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/livecode/livecode/pulls/3495"},"html":{"href":"https://github.com/livecode/livecode/pull/3495"},"issue":{"href":"https://api.github.com/repos/livecode/livecode/issues/3495"},"comments":{"href":"https://api.github.com/repos/livecode/livecode/issues/3495/comments"},"review_comments":{"href":"https://api.github.com/repos/livecode/livecode/pulls/3495/comments"},"review_comment":{"href":"https://api.github.com/repos/livecode/livecode/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/livecode/livecode/pulls/3495/commits"},"statuses":{"href":"https://api.github.com/repos/livecode/livecode/statuses/6d22358edb4e13b6dda827283eb30d0bb6d2f723"}}}}