Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
renderjs
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
renderjs
Commits
84bcf0e9
Commit
84bcf0e9
authored
Jul 31, 2017
by
Romain Courteaud
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Iframe: ensure all channels are OK before calling ready
parent
987147b7
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
361 additions
and
383 deletions
+361
-383
renderjs.js
renderjs.js
+345
-369
test/embedded.js
test/embedded.js
+1
-2
test/renderjs_test.js
test/renderjs_test.js
+14
-8
test/trigger_rjsready_event_on_ready_gadget.js
test/trigger_rjsready_event_on_ready_gadget.js
+1
-4
No files found.
renderjs.js
View file @
84bcf0e9
...
@@ -139,14 +139,13 @@
...
@@ -139,14 +139,13 @@
javascript_registration_dict
=
{},
javascript_registration_dict
=
{},
stylesheet_registration_dict
=
{},
stylesheet_registration_dict
=
{},
gadget_loading_klass_list
=
[],
gadget_loading_klass_list
=
[],
loading_klass_promise
,
renderJS
,
renderJS
,
Monitor
,
Monitor
,
scope_increment
=
0
,
scope_increment
=
0
,
isAbsoluteOrDataURL
=
new
RegExp
(
'
^(?:[a-z]+:)?//|data:
'
,
'
i
'
),
isAbsoluteOrDataURL
=
new
RegExp
(
'
^(?:[a-z]+:)?//|data:
'
,
'
i
'
),
is_page_unloaded
=
false
,
is_page_unloaded
=
false
,
error_list
=
[],
error_list
=
[],
bootstrap_deferred_object
=
new
RSVP
.
defer
()
;
all_dependency_loaded_deferred
;
window
.
addEventListener
(
'
error
'
,
function
(
error
)
{
window
.
addEventListener
(
'
error
'
,
function
(
error
)
{
error_list
.
push
(
error
);
error_list
.
push
(
error
);
...
@@ -900,7 +899,8 @@
...
@@ -900,7 +899,8 @@
// Create the communication channel with the iframe
// Create the communication channel with the iframe
gadget_instance
.
__chan
=
Channel
.
build
({
gadget_instance
.
__chan
=
Channel
.
build
({
window
:
iframe
.
contentWindow
,
window
:
iframe
.
contentWindow
,
origin
:
"
*
"
,
// origin: (new URL(url, window.location)).origin,
origin
:
'
*
'
,
scope
:
"
renderJS
"
scope
:
"
renderJS
"
});
});
...
@@ -915,12 +915,8 @@
...
@@ -915,12 +915,8 @@
params
:
[
params
:
[
method_name
,
method_name
,
Array
.
prototype
.
slice
.
call
(
argument_list
,
0
)],
Array
.
prototype
.
slice
.
call
(
argument_list
,
0
)],
success
:
function
(
s
)
{
success
:
resolve
,
resolve
(
s
);
error
:
reject
},
error
:
function
(
e
)
{
reject
(
e
);
}
});
});
});
});
return
new
RSVP
.
Queue
()
return
new
RSVP
.
Queue
()
...
@@ -1255,9 +1251,6 @@
...
@@ -1255,9 +1251,6 @@
gadget_model_defer_dict
[
url
]
=
defer
;
gadget_model_defer_dict
[
url
]
=
defer
;
// Change the global variable to update the loading queue
loading_klass_promise
=
defer
.
promise
;
// Fetch the HTML page and parse it
// Fetch the HTML page and parse it
return
new
RSVP
.
Queue
()
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
()
{
...
@@ -1370,402 +1363,385 @@
...
@@ -1370,402 +1363,385 @@
// Bootstrap process. Register the self gadget.
// Bootstrap process. Register the self gadget.
///////////////////////////////////////////////////
///////////////////////////////////////////////////
// Detect when all JS dependencies have been loaded
all_dependency_loaded_deferred
=
new
RSVP
.
defer
();
// Manually initializes the self gadget if the DOMContentLoaded event
// Manually initializes the self gadget if the DOMContentLoaded event
// is triggered before everything was ready.
// is triggered before everything was ready.
// (For instance, the HTML-tag for the self gadget gets inserted after
// (For instance, the HTML-tag for the self gadget gets inserted after
// page load)
// page load)
renderJS
.
manualBootstrap
=
function
()
{
renderJS
.
manualBootstrap
=
function
()
{
bootstrap_deferred_object
.
resolve
();
all_dependency_loaded_deferred
.
resolve
();
};
};
document
.
addEventListener
(
'
DOMContentLoaded
'
,
all_dependency_loaded_deferred
.
resolve
,
false
);
function
configureMutationObserver
(
TmpConstructor
,
url
,
root_gadget
)
{
// XXX HTML properties can only be set when the DOM is fully loaded
var
settings
=
renderJS
.
parseGadgetHTMLDocument
(
document
,
url
),
j
,
key
,
fragment
=
document
.
createDocumentFragment
();
for
(
key
in
settings
)
{
if
(
settings
.
hasOwnProperty
(
key
))
{
TmpConstructor
.
prototype
[
'
__
'
+
key
]
=
settings
[
key
];
}
}
TmpConstructor
.
__template_element
=
document
.
createElement
(
"
div
"
);
root_gadget
.
element
=
document
.
body
;
root_gadget
.
state
=
{};
for
(
j
=
0
;
j
<
root_gadget
.
element
.
childNodes
.
length
;
j
+=
1
)
{
fragment
.
appendChild
(
root_gadget
.
element
.
childNodes
[
j
].
cloneNode
(
true
)
);
}
TmpConstructor
.
__template_element
.
appendChild
(
fragment
);
return
RSVP
.
all
([
root_gadget
.
getRequiredJSList
(),
root_gadget
.
getRequiredCSSList
()])
.
then
(
function
(
all_list
)
{
var
i
,
js_list
=
all_list
[
0
],
css_list
=
all_list
[
1
];
for
(
i
=
0
;
i
<
js_list
.
length
;
i
+=
1
)
{
javascript_registration_dict
[
js_list
[
i
]]
=
null
;
}
for
(
i
=
0
;
i
<
css_list
.
length
;
i
+=
1
)
{
stylesheet_registration_dict
[
css_list
[
i
]]
=
null
;
}
gadget_loading_klass_list
.
shift
();
}).
then
(
function
()
{
// select the target node
var
target
=
document
.
querySelector
(
'
body
'
),
// create an observer instance
observer
=
new
MutationObserver
(
function
(
mutations
)
{
var
i
,
k
,
len
,
len2
,
node
,
added_list
;
mutations
.
forEach
(
function
(
mutation
)
{
if
(
mutation
.
type
===
'
childList
'
)
{
len
=
mutation
.
removedNodes
.
length
;
for
(
i
=
0
;
i
<
len
;
i
+=
1
)
{
node
=
mutation
.
removedNodes
[
i
];
if
(
node
.
nodeType
===
Node
.
ELEMENT_NODE
)
{
if
(
node
.
hasAttribute
(
"
data-gadget-url
"
)
&&
(
node
.
_gadget
!==
undefined
))
{
createMonitor
(
node
.
_gadget
);
}
added_list
=
node
.
querySelectorAll
(
"
[data-gadget-url]
"
);
len2
=
added_list
.
length
;
for
(
k
=
0
;
k
<
len2
;
k
+=
1
)
{
node
=
added_list
[
k
];
if
(
node
.
_gadget
!==
undefined
)
{
createMonitor
(
node
.
_gadget
);
}
}
}
}
function
bootstrap
()
{
len
=
mutation
.
addedNodes
.
length
;
var
url
=
removeHash
(
window
.
location
.
href
),
for
(
i
=
0
;
i
<
len
;
i
+=
1
)
{
TmpConstructor
,
node
=
mutation
.
addedNodes
[
i
];
if
(
node
.
nodeType
===
Node
.
ELEMENT_NODE
)
{
if
(
node
.
hasAttribute
(
"
data-gadget-url
"
)
&&
(
node
.
_gadget
!==
undefined
))
{
if
(
document
.
contains
(
node
))
{
startService
(
node
.
_gadget
);
}
}
added_list
=
node
.
querySelectorAll
(
"
[data-gadget-url]
"
);
len2
=
added_list
.
length
;
for
(
k
=
0
;
k
<
len2
;
k
+=
1
)
{
node
=
added_list
[
k
];
if
(
document
.
contains
(
node
))
{
if
(
node
.
_gadget
!==
undefined
)
{
startService
(
node
.
_gadget
);
}
}
}
}
}
}
});
}),
// configuration of the observer:
config
=
{
childList
:
true
,
subtree
:
true
,
attributes
:
false
,
characterData
:
false
};
// pass in the target node, as well as the observer options
observer
.
observe
(
target
,
config
);
return
root_gadget
;
});
}
function
createLastAcquisitionGadget
()
{
var
last_acquisition_gadget
=
new
RenderJSGadget
();
last_acquisition_gadget
.
__acquired_method_dict
=
{
reportServiceError
:
function
(
param_list
)
{
letsCrash
(
param_list
[
0
]);
}
};
// Stop acquisition on the last acquisition gadget
// Do not put this on the klass, as their could be multiple instances
last_acquisition_gadget
.
__aq_parent
=
function
(
method_name
)
{
throw
new
renderJS
.
AcquisitionError
(
"
No gadget provides
"
+
method_name
);
};
return
last_acquisition_gadget
;
}
/*
function notifyAllMethodToParent() {
;
}
*/
function
createLoadingGadget
(
url
)
{
var
TmpConstructor
,
root_gadget
,
root_gadget
,
loading_gadget_promise
=
new
RSVP
.
Queue
(),
declare_method_count
=
0
,
embedded_channel
,
embedded_channel
,
notifyReady
,
notifyDeclareMethod
,
notifyDeclareMethod
,
gadget_ready
=
false
,
declare_method_list_waiting
,
iframe_top_gadget
,
loading_result
,
last_acquisition_gadget
,
channel_defer
,
declare_method_list_waiting
=
[],
real_result_list
;
gadget_failed
=
false
,
// gadget_failed = false,
gadget_error
,
// connection_ready = false;
connection_ready
=
false
;
// Create the gadget class for the current url
// Create the gadget class for the current url
if
(
gadget_model_defer_dict
.
hasOwnProperty
(
url
))
{
if
(
gadget_model_defer_dict
.
hasOwnProperty
(
url
))
{
throw
new
Error
(
"
bootstrap should not be called twice
"
);
throw
new
Error
(
"
bootstrap should not be called twice
"
);
}
}
loading_klass_promise
=
new
RSVP
.
Promise
(
function
(
resolve
,
reject
)
{
last_acquisition_gadget
=
new
RenderJSGadget
();
last_acquisition_gadget
.
__acquired_method_dict
=
{
reportServiceError
:
function
(
param_list
)
{
letsCrash
(
param_list
[
0
]);
}
};
// Stop acquisition on the last acquisition gadget
// Do not put this on the klass, as their could be multiple instances
last_acquisition_gadget
.
__aq_parent
=
function
(
method_name
)
{
throw
new
renderJS
.
AcquisitionError
(
"
No gadget provides
"
+
method_name
);
};
//we need to determine tmp_constructor's value before exit bootstrap
//because of function : renderJS
//but since the channel checking is async,
//we can't use code structure like:
// if channel communication is ok
// tmp_constructor = RenderJSGadget
// else
// tmp_constructor = RenderJSEmbeddedGadget
if
(
window
.
self
===
window
.
top
)
{
// XXX Copy/Paste from declareGadgetKlass
TmpConstructor
=
function
()
{
RenderJSGadget
.
call
(
this
);
};
TmpConstructor
.
declareMethod
=
RenderJSGadget
.
declareMethod
;
TmpConstructor
.
declareJob
=
RenderJSGadget
.
declareJob
;
TmpConstructor
.
declareAcquiredMethod
=
RenderJSGadget
.
declareAcquiredMethod
;
TmpConstructor
.
allowPublicAcquisition
=
RenderJSGadget
.
allowPublicAcquisition
;
TmpConstructor
.
__ready_list
=
RenderJSGadget
.
__ready_list
.
slice
();
TmpConstructor
.
ready
=
RenderJSGadget
.
ready
;
TmpConstructor
.
setState
=
RenderJSGadget
.
setState
;
TmpConstructor
.
onStateChange
=
RenderJSGadget
.
onStateChange
;
TmpConstructor
.
__service_list
=
RenderJSGadget
.
__service_list
.
slice
();
TmpConstructor
.
declareService
=
RenderJSGadget
.
declareService
;
TmpConstructor
.
onEvent
=
RenderJSGadget
.
onEvent
;
TmpConstructor
.
onLoop
=
RenderJSGadget
.
onLoop
;
TmpConstructor
.
prototype
=
new
RenderJSGadget
();
TmpConstructor
.
prototype
.
constructor
=
TmpConstructor
;
TmpConstructor
.
prototype
.
__path
=
url
;
gadget_model_defer_dict
[
url
]
=
{
promise
:
RSVP
.
resolve
(
TmpConstructor
)
};
// Create the root gadget instance and put it in the loading stack
root_gadget
=
new
TmpConstructor
();
setAqParent
(
root_gadget
,
last_acquisition_gadget
);
// Create the root gadget instance and put it in the loading stack
TmpConstructor
=
RenderJSEmbeddedGadget
;
TmpConstructor
.
__ready_list
=
RenderJSGadget
.
__ready_list
.
slice
();
TmpConstructor
.
__service_list
=
RenderJSGadget
.
__service_list
.
slice
();
TmpConstructor
.
prototype
.
__path
=
url
;
root_gadget
=
new
RenderJSEmbeddedGadget
();
setAqParent
(
root_gadget
,
createLastAcquisitionGadget
());
declare_method_list_waiting
=
[
"
getInterfaceList
"
,
"
getRequiredCSSList
"
,
"
getRequiredJSList
"
,
"
getPath
"
,
"
getTitle
"
];
// Inform parent gadget about declareMethod calls here.
notifyDeclareMethod
=
function
(
name
)
{
declare_method_list_waiting
.
push
(
name
);
};
}
else
{
real_result_list
=
[
TmpConstructor
,
root_gadget
,
embedded_channel
,
// Create the root gadget instance and put it in the loading stack
declare_method_list_waiting
];
TmpConstructor
=
RenderJSEmbeddedGadget
;
if
(
window
.
self
===
window
.
top
)
{
TmpConstructor
.
__ready_list
=
RenderJSGadget
.
__ready_list
.
slice
();
loading_result
=
real_result_list
;
TmpConstructor
.
__service_list
=
RenderJSGadget
.
__service_list
.
slice
();
}
else
{
TmpConstructor
.
prototype
.
__path
=
url
;
channel_defer
=
RSVP
.
defer
();
root_gadget
=
new
RenderJSEmbeddedGadget
();
loading_result
=
RSVP
.
any
([
setAqParent
(
root_gadget
,
last_acquisition_gadget
);
channel_defer
.
promise
,
new
RSVP
.
Queue
()
// Create the communication channel
.
push
(
function
()
{
embedded_channel
=
Channel
.
build
({
// Expect the channel to parent to be usable after 1 second
window
:
window
.
parent
,
// If not, consider the gadget as the root
origin
:
"
*
"
,
// Drop all iframe channel communication
scope
:
"
renderJS
"
,
return
RSVP
.
delay
(
1000
);
onReady
:
function
()
{
})
var
k
;
.
push
(
function
()
{
iframe_top_gadget
=
false
;
real_result_list
[
2
]
=
undefined
;
//Default: Define __aq_parent to inform parent window
return
real_result_list
;
root_gadget
.
__aq_parent
=
})
TmpConstructor
.
prototype
.
__aq_parent
=
function
(
method_name
,
]);
argument_list
,
time_out
)
{
// Create the communication channel
return
new
RSVP
.
Promise
(
function
(
resolve
,
reject
)
{
embedded_channel
=
Channel
.
build
({
embedded_channel
.
call
({
window
:
window
.
parent
,
method
:
"
acquire
"
,
origin
:
"
*
"
,
params
:
[
scope
:
"
renderJS
"
,
method_name
,
onReady
:
function
()
{
argument_list
var
k
,
],
len
;
success
:
function
(
s
)
{
// Channel is ready, so now declare all methods
resolve
(
s
);
notifyDeclareMethod
=
function
(
name
)
{
},
declare_method_list_waiting
.
push
(
error
:
function
(
e
)
{
new
RSVP
.
Promise
(
function
(
resolve
,
reject
)
{
reject
(
e
);
embedded_channel
.
call
({
},
method
:
"
declareMethod
"
,
timeout
:
time_out
params
:
name
,
});
success
:
resolve
,
});
error
:
reject
};
// Channel is ready, so now declare Function
notifyDeclareMethod
=
function
(
name
)
{
declare_method_count
+=
1
;
embedded_channel
.
call
({
method
:
"
declareMethod
"
,
params
:
name
,
success
:
function
()
{
declare_method_count
-=
1
;
notifyReady
();
},
error
:
function
()
{
declare_method_count
-=
1
;
}
});
};
for
(
k
=
0
;
k
<
declare_method_list_waiting
.
length
;
k
+=
1
)
{
notifyDeclareMethod
(
declare_method_list_waiting
[
k
]);
}
declare_method_list_waiting
=
[];
// If Gadget Failed Notify Parent
if
(
gadget_failed
)
{
embedded_channel
.
notify
({
method
:
"
failed
"
,
params
:
gadget_error
});
return
;
}
connection_ready
=
true
;
notifyReady
();
//the channel is ok
//so bind calls to renderJS method on the instance
embedded_channel
.
bind
(
"
methodCall
"
,
function
(
trans
,
v
)
{
root_gadget
[
v
[
0
]].
apply
(
root_gadget
,
v
[
1
])
.
then
(
function
(
g
)
{
trans
.
complete
(
g
);
}).
fail
(
function
(
e
)
{
trans
.
error
(
e
.
toString
());
});
});
trans
.
delayReturn
(
true
);
})
});
);
}
};
});
// Notify parent about gadget instanciation
len
=
declare_method_list_waiting
.
length
;
notifyReady
=
function
()
{
for
(
k
=
0
;
k
<
len
;
k
+=
1
)
{
if
((
declare_method_count
===
0
)
&&
(
gadget_ready
===
true
))
{
notifyDeclareMethod
(
declare_method_list_waiting
[
k
]);
embedded_channel
.
notify
({
method
:
"
ready
"
});
}
}
};
// Inform parent gadget about declareMethod calls here.
channel_defer
.
resolve
(
real_result_list
);
notifyDeclareMethod
=
function
(
name
)
{
}
declare_method_list_waiting
.
push
(
name
);
});
};
real_result_list
[
2
]
=
embedded_channel
;
}
notifyDeclareMethod
(
"
getInterfaceList
"
);
// Surcharge declareMethod to inform parent window
notifyDeclareMethod
(
"
getRequiredCSSList
"
);
TmpConstructor
.
declareMethod
=
function
(
name
,
callback
)
{
notifyDeclareMethod
(
"
getRequiredJSList
"
);
var
result
=
RenderJSGadget
.
declareMethod
.
apply
(
notifyDeclareMethod
(
"
getPath
"
);
this
,
notifyDeclareMethod
(
"
getTitle
"
);
[
name
,
callback
]
);
// Surcharge declareMethod to inform parent window
notifyDeclareMethod
(
name
);
TmpConstructor
.
declareMethod
=
function
(
name
,
callback
)
{
return
result
;
var
result
=
RenderJSGadget
.
declareMethod
.
apply
(
};
this
,
[
name
,
callback
]
);
notifyDeclareMethod
(
name
);
return
result
;
};
TmpConstructor
.
declareService
=
TmpConstructor
.
declareService
=
RenderJSGadget
.
declareService
;
RenderJSGadget
.
declareService
;
TmpConstructor
.
declareJob
=
TmpConstructor
.
declareJob
=
RenderJSGadget
.
declareJob
;
RenderJSGadget
.
declareJob
;
TmpConstructor
.
onEvent
=
TmpConstructor
.
onEvent
=
RenderJSGadget
.
onEvent
;
RenderJSGadget
.
onEvent
;
TmpConstructor
.
onLoop
=
TmpConstructor
.
onLoop
=
RenderJSGadget
.
onLoop
;
RenderJSGadget
.
onLoop
;
TmpConstructor
.
declareAcquiredMethod
=
TmpConstructor
.
declareAcquiredMethod
=
RenderJSGadget
.
declareAcquiredMethod
;
RenderJSGadget
.
declareAcquiredMethod
;
TmpConstructor
.
allowPublicAcquisition
=
TmpConstructor
.
allowPublicAcquisition
=
RenderJSGadget
.
allowPublicAcquisition
;
RenderJSGadget
.
allowPublicAcquisition
;
iframe_top_gadget
=
true
;
}
TmpConstructor
.
prototype
.
__acquired_method_dict
=
{};
TmpConstructor
.
prototype
.
__acquired_method_dict
=
{};
gadget_loading_klass_list
.
push
(
TmpConstructor
);
gadget_loading_klass_list
.
push
(
TmpConstructor
);
function
init
()
{
return
loading_result
;
// XXX HTML properties can only be set when the DOM is fully loaded
}
var
settings
=
renderJS
.
parseGadgetHTMLDocument
(
document
,
url
),
j
,
key
,
fragment
=
document
.
createDocumentFragment
();
for
(
key
in
settings
)
{
if
(
settings
.
hasOwnProperty
(
key
))
{
TmpConstructor
.
prototype
[
'
__
'
+
key
]
=
settings
[
key
];
}
}
TmpConstructor
.
__template_element
=
document
.
createElement
(
"
div
"
);
root_gadget
.
element
=
document
.
body
;
root_gadget
.
state
=
{};
for
(
j
=
0
;
j
<
root_gadget
.
element
.
childNodes
.
length
;
j
+=
1
)
{
fragment
.
appendChild
(
root_gadget
.
element
.
childNodes
[
j
].
cloneNode
(
true
)
);
}
TmpConstructor
.
__template_element
.
appendChild
(
fragment
);
RSVP
.
all
([
root_gadget
.
getRequiredJSList
(),
root_gadget
.
getRequiredCSSList
()])
.
then
(
function
(
all_list
)
{
var
i
,
js_list
=
all_list
[
0
],
css_list
=
all_list
[
1
];
for
(
i
=
0
;
i
<
js_list
.
length
;
i
+=
1
)
{
javascript_registration_dict
[
js_list
[
i
]]
=
null
;
}
for
(
i
=
0
;
i
<
css_list
.
length
;
i
+=
1
)
{
stylesheet_registration_dict
[
css_list
[
i
]]
=
null
;
}
gadget_loading_klass_list
.
shift
();
}).
then
(
function
()
{
// select the target node
var
target
=
document
.
querySelector
(
'
body
'
),
// create an observer instance
observer
=
new
MutationObserver
(
function
(
mutations
)
{
var
i
,
k
,
len
,
len2
,
node
,
added_list
;
mutations
.
forEach
(
function
(
mutation
)
{
if
(
mutation
.
type
===
'
childList
'
)
{
len
=
mutation
.
removedNodes
.
length
;
for
(
i
=
0
;
i
<
len
;
i
+=
1
)
{
node
=
mutation
.
removedNodes
[
i
];
if
(
node
.
nodeType
===
Node
.
ELEMENT_NODE
)
{
if
(
node
.
hasAttribute
(
"
data-gadget-url
"
)
&&
(
node
.
_gadget
!==
undefined
))
{
createMonitor
(
node
.
_gadget
);
}
added_list
=
node
.
querySelectorAll
(
"
[data-gadget-url]
"
);
len2
=
added_list
.
length
;
for
(
k
=
0
;
k
<
len2
;
k
+=
1
)
{
node
=
added_list
[
k
];
if
(
node
.
_gadget
!==
undefined
)
{
createMonitor
(
node
.
_gadget
);
}
}
}
}
len
=
mutation
.
addedNodes
.
length
;
function
triggerReadyList
(
TmpConstructor
,
root_gadget
)
{
for
(
i
=
0
;
i
<
len
;
i
+=
1
)
{
// XXX Probably duplicated
node
=
mutation
.
addedNodes
[
i
];
var
i
,
if
(
node
.
nodeType
===
Node
.
ELEMENT_NODE
)
{
ready_queue
=
new
RSVP
.
Queue
();
if
(
node
.
hasAttribute
(
"
data-gadget-url
"
)
&&
(
node
.
_gadget
!==
undefined
))
{
if
(
document
.
contains
(
node
))
{
startService
(
node
.
_gadget
);
}
}
added_list
=
node
.
querySelectorAll
(
"
[data-gadget-url]
"
);
len2
=
added_list
.
length
;
for
(
k
=
0
;
k
<
len2
;
k
+=
1
)
{
node
=
added_list
[
k
];
if
(
document
.
contains
(
node
))
{
if
(
node
.
_gadget
!==
undefined
)
{
startService
(
node
.
_gadget
);
}
}
}
}
}
}
function
ready_wrapper
()
{
});
return
root_gadget
;
}),
}
// configuration of the observer:
function
ready_executable_wrapper
(
fct
)
{
config
=
{
return
function
(
g
)
{
childList
:
true
,
return
fct
.
call
(
g
,
g
);
subtree
:
true
,
};
attributes
:
false
,
}
characterData
:
false
TmpConstructor
.
ready
(
function
()
{
};
return
startService
(
this
);
});
// pass in the target node, as well as the observer options
observer
.
observe
(
target
,
config
);
ready_queue
.
push
(
ready_wrapper
);
for
(
i
=
0
;
i
<
TmpConstructor
.
__ready_list
.
length
;
i
+=
1
)
{
return
root_gadget
;
// Put a timeout?
}).
then
(
resolve
,
function
(
e
)
{
ready_queue
reject
(
e
);
.
push
(
ready_executable_wrapper
(
TmpConstructor
.
__ready_list
[
i
]))
console
.
error
(
e
);
// Always return the gadget instance after ready function
throw
e
;
.
push
(
ready_wrapper
);
}
return
ready_queue
;
}
function
finishAqParentConfiguration
(
TmpConstructor
,
root_gadget
,
embedded_channel
)
{
// Define __aq_parent to inform parent window
root_gadget
.
__aq_parent
=
TmpConstructor
.
prototype
.
__aq_parent
=
function
(
method_name
,
argument_list
,
time_out
)
{
return
new
RSVP
.
Promise
(
function
(
resolve
,
reject
)
{
embedded_channel
.
call
({
method
:
"
acquire
"
,
params
:
[
method_name
,
argument_list
],
success
:
function
(
s
)
{
resolve
(
s
);
},
error
:
function
(
e
)
{
reject
(
e
);
},
timeout
:
time_out
});
});
}
document
.
addEventListener
(
'
DOMContentLoaded
'
,
bootstrap_deferred_object
.
resolve
,
false
);
// Return Promies/Queue here instead of directly calling init()
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
bootstrap_deferred_object
.
promise
;
})
.
push
(
function
()
{
return
init
();
});
});
};
// bind calls to renderJS method on the instance
embedded_channel
.
bind
(
"
methodCall
"
,
function
(
trans
,
v
)
{
root_gadget
[
v
[
0
]].
apply
(
root_gadget
,
v
[
1
])
.
push
(
function
(
g
)
{
trans
.
complete
(
g
);
},
function
(
e
)
{
trans
.
error
(
e
.
toString
());
});
trans
.
delayReturn
(
true
);
});
});
}
function
bootstrap
(
url
)
{
// Create the loading gadget
var
wait_for_gadget_loaded
=
createLoadingGadget
(
url
),
TmpConstructor
,
root_gadget
,
embedded_channel
,
declare_method_list_waiting
;
loading_gadget_promise
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
()
{
return
loading_klass_promise
;
// Wait for the loading gadget to be created
return
wait_for_gadget_loaded
;
})
})
.
push
(
function
(
root_gadget
)
{
.
push
(
function
(
result_list
)
{
var
i
;
TmpConstructor
=
result_list
[
0
];
root_gadget
=
result_list
[
1
];
function
ready_wrapper
()
{
embedded_channel
=
result_list
[
2
];
return
root_gadget
;
declare_method_list_waiting
=
result_list
[
3
];
// Wait for all the gadget dependencies to be loaded
return
all_dependency_loaded_deferred
.
promise
;
})
.
push
(
function
()
{
// Wait for all methods to be correctly declared
return
RSVP
.
all
(
declare_method_list_waiting
);
})
.
push
(
function
(
result_list
)
{
if
(
embedded_channel
!==
undefined
)
{
finishAqParentConfiguration
(
TmpConstructor
,
root_gadget
,
embedded_channel
);
}
}
function
ready_executable_wrapper
(
fct
)
{
// Check all DOM modifications to correctly start/stop services
return
function
(
g
)
{
return
configureMutationObserver
(
TmpConstructor
,
url
,
root_gadget
);
return
fct
.
call
(
g
,
g
);
})
};
.
push
(
function
()
{
// Trigger all ready functions
return
triggerReadyList
(
TmpConstructor
,
root_gadget
);
})
.
push
(
function
()
{
if
(
embedded_channel
!==
undefined
)
{
embedded_channel
.
notify
({
method
:
"
ready
"
});
}
}
TmpConstructor
.
ready
(
function
()
{
})
return
startService
(
this
);
.
push
(
undefined
,
function
(
e
)
{
});
letsCrash
(
e
);
if
(
embedded_channel
!==
undefined
)
{
loading_gadget_promise
.
push
(
ready_wrapper
);
embedded_channel
.
notify
({
method
:
"
failed
"
,
params
:
e
.
toString
()});
for
(
i
=
0
;
i
<
TmpConstructor
.
__ready_list
.
length
;
i
+=
1
)
{
// Put a timeout?
loading_gadget_promise
.
push
(
ready_executable_wrapper
(
TmpConstructor
.
__ready_list
[
i
]))
// Always return the gadget instance after ready function
.
push
(
ready_wrapper
);
}
}
throw
e
;
});
});
if
(
window
.
self
===
window
.
top
)
{
loading_gadget_promise
.
fail
(
function
(
e
)
{
letsCrash
(
e
);
throw
e
;
});
}
else
{
// Inform parent window that gadget is correctly loaded
loading_gadget_promise
.
then
(
function
()
{
gadget_ready
=
true
;
if
(
connection_ready
)
{
notifyReady
();
}
})
.
fail
(
function
(
e
)
{
//top gadget in iframe
if
(
iframe_top_gadget
)
{
gadget_failed
=
true
;
gadget_error
=
e
.
toString
();
letsCrash
(
e
);
}
else
{
embedded_channel
.
notify
({
method
:
"
failed
"
,
params
:
e
.
toString
()});
}
throw
e
;
});
}
}
}
bootstrap
();
bootstrap
(
removeHash
(
window
.
location
.
href
)
);
}(
document
,
window
,
RSVP
,
DOMParser
,
Channel
,
MutationObserver
,
Node
,
}(
document
,
window
,
RSVP
,
DOMParser
,
Channel
,
MutationObserver
,
Node
,
FileReader
,
Blob
,
navigator
,
Event
,
URL
));
FileReader
,
Blob
,
navigator
,
Event
,
URL
));
test/embedded.js
View file @
84bcf0e9
...
@@ -15,8 +15,7 @@
...
@@ -15,8 +15,7 @@
(
modification_dict
.
foo
===
'
bar
'
);
(
modification_dict
.
foo
===
'
bar
'
);
state_change_count
+=
1
;
state_change_count
+=
1
;
};
};
gk
.
ready
(
function
()
{
gk
.
ready
(
function
(
g
)
{
ready_called
=
true
;
ready_called
=
true
;
})
})
.
setState
(
init_state
)
.
setState
(
init_state
)
...
...
test/renderjs_test.js
View file @
84bcf0e9
...
@@ -4868,7 +4868,8 @@
...
@@ -4868,7 +4868,8 @@
// Check that declare gadget returns the gadget
// Check that declare gadget returns the gadget
var
gadget
=
new
RenderJSGadget
(),
var
gadget
=
new
RenderJSGadget
(),
acquire_called
=
false
,
acquire_called
=
false
,
url
=
"
./embedded.html
"
;
url
=
"
./embedded.html
"
,
new_gadget
;
gadget
.
__aq_parent
=
function
(
method_name
,
argument_list
)
{
gadget
.
__aq_parent
=
function
(
method_name
,
argument_list
)
{
acquire_called
=
true
;
acquire_called
=
true
;
...
@@ -4889,9 +4890,11 @@
...
@@ -4889,9 +4890,11 @@
stop
();
stop
();
gadget
.
declareGadget
(
url
,
{
gadget
.
declareGadget
(
url
,
{
sandbox
:
'
iframe
'
,
sandbox
:
'
iframe
'
,
element
:
document
.
getElementById
(
'
qunit-fixture
'
)
element
:
document
.
getElementById
(
'
qunit-fixture
'
),
scope
:
'
foobar
'
})
})
.
then
(
function
(
new_gadget
)
{
.
then
(
function
(
sub_gadget
)
{
new_gadget
=
sub_gadget
;
return
new
RSVP
.
Queue
()
return
new
RSVP
.
Queue
()
// Method returns an RSVP.Queue
// Method returns an RSVP.Queue
...
@@ -4901,12 +4904,14 @@
...
@@ -4901,12 +4904,14 @@
result
instanceof
RSVP
.
Queue
,
result
instanceof
RSVP
.
Queue
,
"
iframe method should return Queue
"
"
iframe method should return Queue
"
);
);
return
result
;
})
})
/*
// Check that ready function are called
// Check that ready function are called
.push(function () {
.push(function () {
return new_gadget.wasReadyCalled();
return new_gadget.wasReadyCalled();
})
})
*/
.
push
(
function
(
result
)
{
.
push
(
function
(
result
)
{
equal
(
result
,
true
);
equal
(
result
,
true
);
})
})
...
@@ -5776,7 +5781,7 @@
...
@@ -5776,7 +5781,7 @@
fixture
.
innerHTML
=
fixture
.
innerHTML
=
"
<iframe id=renderjsIframe src='./not_declared_gadget.html'></iframe>
"
;
"
<iframe id=renderjsIframe src='./not_declared_gadget.html'></iframe>
"
;
stop
();
stop
();
return
RSVP
.
delay
(
9
00
)
return
RSVP
.
delay
(
15
00
)
.
then
(
function
()
{
.
then
(
function
()
{
var
iframe
=
document
.
getElementById
(
'
renderjsIframe
'
),
var
iframe
=
document
.
getElementById
(
'
renderjsIframe
'
),
acquisition_div
=
iframe
.
contentWindow
.
acquisition_div
=
iframe
.
contentWindow
.
...
@@ -5820,8 +5825,6 @@
...
@@ -5820,8 +5825,6 @@
return
;
return
;
}
}
iframe_text
=
iframe_body
.
textContent
;
iframe_text
=
iframe_body
.
textContent
;
/*global console*/
// console.log(iframe_text);
if
(
iframe_text
.
indexOf
(
'
Page changed
'
)
!==
-
1
)
{
if
(
iframe_text
.
indexOf
(
'
Page changed
'
)
!==
-
1
)
{
// Final page
// Final page
ok
(
true
,
iframe_text
);
ok
(
true
,
iframe_text
);
...
@@ -5873,6 +5876,9 @@
...
@@ -5873,6 +5876,9 @@
resolve
(
evt
.
target
.
result
);
resolve
(
evt
.
target
.
result
);
});
});
})
})
.
then
(
function
()
{
return
RSVP
.
delay
(
1100
);
})
.
then
(
function
()
{
.
then
(
function
()
{
var
iframe_body
=
iframe
.
contentWindow
.
document
.
body
,
var
iframe_body
=
iframe
.
contentWindow
.
document
.
body
,
iframe_text
=
iframe_body
.
textContent
;
iframe_text
=
iframe_body
.
textContent
;
...
@@ -5946,7 +5952,7 @@
...
@@ -5946,7 +5952,7 @@
// if no event is fired within 500ms, just resolve and fail later
// if no event is fired within 500ms, just resolve and fail later
window
.
setTimeout
(
function
()
{
window
.
setTimeout
(
function
()
{
reject
(
"
Timeout, RenderJS is not Ready
"
);
reject
(
"
Timeout, RenderJS is not Ready
"
);
},
5
00
);
},
30
00
);
iframe
.
contentWindow
.
rJS
.
manualBootstrap
();
iframe
.
contentWindow
.
rJS
.
manualBootstrap
();
});
});
})
})
...
...
test/trigger_rjsready_event_on_ready_gadget.js
View file @
84bcf0e9
...
@@ -6,9 +6,6 @@
...
@@ -6,9 +6,6 @@
rJS
(
window
)
rJS
(
window
)
.
ready
(
function
(
gadget
)
{
.
ready
(
function
(
gadget
)
{
return
gadget
.
getElement
()
return
gadget
.
element
.
dispatchEvent
(
new
Event
(
"
rjsready
"
));
.
push
(
function
(
element
)
{
element
.
dispatchEvent
(
new
Event
(
"
rjsready
"
));
});
});
});
}(
window
,
rJS
));
}(
window
,
rJS
));
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment