@@ -341,23 +341,31 @@ static xmlNodePtr dom_xml_fragment_parsing_algorithm(dom_object *obj, const xmlN
341341	return  NULL ;
342342}
343343
344- /* https://w3c.github.io/DOM-Parsing/#the-innerhtml-mixin 
345-  * and https://w3c.github.io/DOM-Parsing/#dfn-fragment-parsing-algorithm */ 
346- zend_result  dom_element_inner_html_write (dom_object  * obj , zval  * newval )
344+ /* https://w3c.github.io/DOM-Parsing/#dfn-fragment-parsing-algorithm */ 
345+ static  xmlNodePtr  dom_parse_fragment (dom_object  * obj , xmlNodePtr  context_node , const  zend_string  * input )
347346{
348- 	DOM_PROP_NODE (xmlNodePtr , context_node , obj );
349- 
350- 	xmlNodePtr  fragment ;
351347	if  (context_node -> doc -> type  ==  XML_DOCUMENT_NODE ) {
352- 		fragment   =   dom_xml_fragment_parsing_algorithm (obj , context_node , Z_STR_P ( newval ) );
348+ 		return   dom_xml_fragment_parsing_algorithm (obj , context_node , input );
353349	} else  {
354- 		fragment   =   dom_html_fragment_parsing_algorithm (obj , context_node , Z_STR_P ( newval ) , obj -> document -> quirks_mode );
350+ 		return   dom_html_fragment_parsing_algorithm (obj , context_node , input , obj -> document -> quirks_mode );
355351	}
352+ }
353+ 
354+ /* https://w3c.github.io/DOM-Parsing/#the-innerhtml-mixin */ 
355+ zend_result  dom_element_inner_html_write (dom_object  * obj , zval  * newval )
356+ {
357+ 	/* 1. We don't do injection sinks, skip. */ 
358+ 
359+ 	/* 2. Let context be this. */ 
360+ 	DOM_PROP_NODE (xmlNodePtr , context_node , obj );
356361
362+ 	/* 3. Let fragment be the result of invoking the fragment parsing algorithm steps with context and compliantString. */ 
363+ 	xmlNodePtr  fragment  =  dom_parse_fragment (obj , context_node , Z_STR_P (newval ));
357364	if  (fragment  ==  NULL ) {
358365		return  FAILURE ;
359366	}
360367
368+ 	/* 4. If context is a template element, then set context to the template element's template contents (a DocumentFragment). */ 
361369	if  (php_dom_ns_is_fast (context_node , php_dom_ns_is_html_magic_token ) &&  xmlStrEqual (context_node -> name , BAD_CAST  "template" )) {
362370		context_node  =  php_dom_ensure_templated_content (php_dom_get_private_data (obj ), context_node );
363371		if  (context_node  ==  NULL ) {
@@ -366,6 +374,7 @@ zend_result dom_element_inner_html_write(dom_object *obj, zval *newval)
366374		}
367375	}
368376
377+ 	/* 5. Replace all with fragment within context. */ 
369378	dom_remove_all_children (context_node );
370379	return  php_dom_pre_insert (obj -> document , fragment , context_node , NULL ) ? SUCCESS  : FAILURE ;
371380}
@@ -397,4 +406,62 @@ zend_result dom_element_outer_html_read(dom_object *obj, zval *retval)
397406	return  SUCCESS ;
398407}
399408
409+ /* https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#the-outerhtml-property */ 
410+ zend_result  dom_element_outer_html_write (dom_object  * obj , zval  * newval )
411+ {
412+ 	/* 1. We don't do injection sinks, skip. */ 
413+ 
414+ 	/* 2. Let parent be this's parent. */ 
415+ 	DOM_PROP_NODE (xmlNodePtr , this , obj );
416+ 	xmlNodePtr  parent  =  this -> parent ;
417+ 	bool  created_parent  =  false;
418+ 
419+ 	/* 3. If parent is null, return. */ 
420+ 	if  (parent  ==  NULL ) {
421+ 		return  SUCCESS ;
422+ 	}
423+ 
424+ 	/* 4. If parent is a Document, throw. */ 
425+ 	if  (parent -> type  ==  XML_DOCUMENT_NODE  ||  parent -> type  ==  XML_HTML_DOCUMENT_NODE ) {
426+ 		php_dom_throw_error (INVALID_MODIFICATION_ERR , true);
427+ 		return  FAILURE ;
428+ 	}
429+ 
430+ 	/* 5. If parent is a DocumentFragment, set parent to the result of creating an element given this's node document, body, and the HTML namespace. */ 
431+ 	if  (parent -> type  ==  XML_DOCUMENT_FRAG_NODE ) {
432+ 		xmlNsPtr  html_ns  =  php_dom_libxml_ns_mapper_ensure_html_ns (php_dom_get_ns_mapper (obj ));
433+ 
434+ 		parent  =  xmlNewDocNode (parent -> doc , html_ns , BAD_CAST  "body" , NULL );
435+ 		created_parent  =  true;
436+ 		if  (UNEXPECTED (parent  ==  NULL )) {
437+ 			php_dom_throw_error (INVALID_STATE_ERR , true);
438+ 			return  FAILURE ;
439+ 		}
440+ 	}
441+ 
442+ 	/* 6. Let fragment be the result of invoking the fragment parsing algorithm steps given parent and compliantString. */ 
443+ 	xmlNodePtr  fragment  =  dom_parse_fragment (obj , parent , Z_STR_P (newval ));
444+ 	if  (fragment  ==  NULL ) {
445+ 		if  (created_parent ) {
446+ 			xmlFreeNode (parent );
447+ 		}
448+ 		return  FAILURE ;
449+ 	}
450+ 
451+ 	/* 7. Replace this with fragment within this's parent. */ 
452+ 	if  (!php_dom_pre_insert (obj -> document , fragment , this -> parent , this )) {
453+ 		xmlFreeNode (fragment );
454+ 		if  (created_parent ) {
455+ 			xmlFreeNode (parent );
456+ 		}
457+ 		return  FAILURE ;
458+ 	}
459+ 	xmlUnlinkNode (this );
460+ 	if  (created_parent ) {
461+ 		ZEND_ASSERT (parent -> children  ==  NULL );
462+ 		xmlFreeNode (parent );
463+ 	}
464+ 	return  SUCCESS ;
465+ }
466+ 
400467#endif 
0 commit comments