/[suikacvs]/messaging/manakai/lib/Message/DOM/Document.pm
Suika

Contents of /messaging/manakai/lib/Message/DOM/Document.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.21 - (hide annotations) (download)
Sun Jul 29 08:31:14 2007 UTC (17 years, 4 months ago) by wakaba
Branch: MAIN
Changes since 1.20: +1088 -4250 lines
++ manakai/lib/Message/DOM/ChangeLog	29 Jul 2007 08:26:38 -0000
	* XDoctype.dis, XDoctype.pm: Removed.

	* CharacterData.pm: Renamed from DOMCharacterData.pm.

	* Document.pm: Renaemd from DOMDocument.pm.

	* Element.pm: Renamed from DOMElement.pm

2007-07-29  Wakaba  <wakaba@suika.fam.cx>

1 wakaba 1.21 ## NOTE: This module will be renamed as Document.pm.
2 wakaba 1.1
3 wakaba 1.21 package Message::DOM::Document;
4     use strict;
5     our $VERSION=do{my @r=(q$Revision: 1.17 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
6     push our @ISA, 'Message::DOM::Node', 'Message::IF::Document',
7     'Message::IF::DocumentTraversal', 'Message::IF::DocumentXDoctype',
8     'Message::IF::HTMLDocument';
9     require Message::DOM::Node;
10     use Char::Class::XML
11     qw/
12     InXML_NameStartChar10 InXMLNameStartChar11
13     InXMLNameChar10 InXMLNameChar11
14     InXML_NCNameStartChar10 InXMLNCNameStartChar11
15     InXMLNCNameChar10 InXMLNCNameChar11
16     /;
17    
18     sub ____new ($$) {
19     my $self = shift->SUPER::____new (undef);
20     $$self->{implementation} = $_[0];
21     $$self->{strict_error_checking} = 1;
22     $$self->{child_nodes} = [];
23     $$self->{'http://suika.fam.cx/www/2006/dom-config/strict-document-children'} = 1;
24     $$self->{'http://suika.fam.cx/www/2006/dom-config/dtd-default-attribute'} = 1;
25     $$self->{'http://suika.fam.cx/www/2006/dom-config/clone-entity-reference-subtree'} = 1;
26     $$self->{'error-handler'} = sub ($) {
27     ## NOTE: Same as one set by |setParameter| with |undef| value.
28     warn $_[0];
29     return $_[0]->severity != 3; # SEVERITY_FATAL_ERROR
30     };
31     return $self;
32     } # ____new
33    
34     sub AUTOLOAD {
35     my $method_name = our $AUTOLOAD;
36     $method_name =~ s/.*:://;
37     return if $method_name eq 'DESTROY';
38 wakaba 1.1
39     if ({
40 wakaba 1.21 ## Read-only attributes (trivial accessors)
41     implementation => 1,
42     }->{$method_name}) {
43     no strict 'refs';
44     eval qq{
45     sub $method_name (\$) {
46     return \${\$_[0]}->{$method_name};
47 wakaba 1.1 }
48 wakaba 1.21 };
49     goto &{ $AUTOLOAD };
50     } elsif ({
51     ## Read-write attributes (DOMString, trivial accessors)
52     document_uri => 1,
53     input_encoding => 1,
54     }->{$method_name}) {
55     no strict 'refs';
56     eval qq{
57     sub $method_name (\$;\$) {
58     if (\@_ > 1) {
59     if (\${\$_[0]}->{strict_error_checking} and
60     \${\$_[0]}->{manakai_read_only}) {
61     report Message::DOM::DOMException
62     -object => \$_[0],
63     -type => 'NO_MODIFICATION_ALLOWED_ERR',
64     -subtype => 'READ_ONLY_NODE_ERR';
65     }
66     if (defined \$_[1]) {
67     \${\$_[0]}->{$method_name} = ''.\$_[1];
68     } else {
69     delete \${\$_[0]}->{$method_name};
70     }
71     }
72     return \${\$_[0]}->{$method_name};
73 wakaba 1.1 }
74 wakaba 1.21 };
75     goto &{ $AUTOLOAD };
76     } elsif ({
77     ## Read-write attributes (boolean, trivial accessors)
78     all_declarations_processed => 1,
79     }->{$method_name}) {
80     no strict 'refs';
81     eval qq{
82     sub $method_name (\$;\$) {
83     if (\@_ > 1) {
84     if (\${\$_[0]}->{manakai_strict_error_checking} and
85     \${\$_[0]}->{manakai_read_only}) {
86     report Message::DOM::DOMException
87     -object => \$_[0],
88     -type => 'NO_MODIFICATION_ALLOWED_ERR',
89     -subtype => 'READ_ONLY_NODE_ERR';
90     }
91     if (\$_[1]) {
92     \${\$_[0]}->{$method_name} = 1;
93     } else {
94     delete \${\$_[0]}->{$method_name};
95 wakaba 1.1 }
96     }
97 wakaba 1.21 return \${\$_[0]}->{$method_name};
98     }
99     };
100     goto &{ $AUTOLOAD };
101     } elsif (my $module_name = {
102     create_attribute => 'Message::DOM::Attr',
103     create_attribute_ns => 'Message::DOM::Attr',
104     create_attribute_definition => 'Message::DOM::AttributeDefinition',
105     create_cdata_section => 'Message::DOM::Text',
106     create_comment => 'Message::DOM::CharacterData',
107     create_document_fragment => 'Message::DOM::DocumentFragment',
108     create_document_type_definition => 'Message::DOM::DocumentType',
109     create_element => 'Message::DOM::Element',
110     create_element_ns => 'Message::DOM::Element',
111     create_element_type_definition => 'Message::DOM::ElementTypeDefinition',
112     create_entity_reference => 'Message::DOM::EntityReference',
113     create_general_entity => 'Message::DOM::Entity',
114     create_notation => 'Message::DOM::Notation',
115     create_processing_instruction => 'Message::DOM::ProcessingInstruction',
116     manakai_create_serial_walker => 'Message::DOM::SerialWalker',
117     create_text_node => 'Message::DOM::Text',
118     create_tree_walker => 'Message::DOM::TreeWalker',
119     }->{$method_name}) {
120     eval qq{ require $module_name } or die $@;
121     goto &{ $AUTOLOAD };
122     } else {
123     require Carp;
124     Carp::croak (qq<Can't locate method "$AUTOLOAD">);
125 wakaba 1.1 }
126 wakaba 1.21 } # AUTOLOAD
127     sub implementation ($);
128     sub create_attribute ($$);
129     sub create_attribute_ns ($$$);
130     sub create_attribute_definition ($$);
131     sub create_cdata_section ($$);
132     sub create_comment ($$);
133     sub create_document_fragment ($);
134     sub create_document_type_definition ($$);
135     sub create_element ($$);
136     sub create_element_ns ($$$);
137     sub create_element_type_definition ($$);
138     sub create_entity_reference ($$);
139     sub create_general_entity ($$);
140     sub create_notation ($$);
141     sub create_processing_instruction ($$$);
142     sub create_text_node ($$);
143    
144     ## |Node| attributes
145    
146     sub base_uri ($) {
147     my $v = ${$_[0]}->{manakai_entity_base_uri};
148     if (defined $v) {
149     return $v;
150     } else {
151     return ${$_[0]}->{document_uri};
152 wakaba 1.13 }
153 wakaba 1.21 ## TODO: HTML5 <base>
154     } # base_uri
155 wakaba 1.1
156 wakaba 1.21 sub node_name () { '#document' }
157 wakaba 1.1
158 wakaba 1.21 sub node_type () { 9 } # DOCUMENT_NODE
159 wakaba 1.1
160 wakaba 1.21 sub text_content ($;$) {
161     my $self = shift;
162     if ($$self->{'http://suika.fam.cx/www/2006/dom-config/strict-document-children'}) {
163     return undef;
164 wakaba 1.1 } else {
165 wakaba 1.21 local $Error::Depth = $Error::Depth + 1;
166     return $self->SUPER::text_content (@_);
167 wakaba 1.1 }
168 wakaba 1.21 } # text_content
169 wakaba 1.1
170 wakaba 1.21 ## |Node| methods
171 wakaba 1.1
172 wakaba 1.21 sub adopt_node ($$) {
173     my ($self, $source) = @_;
174     ## TODO: Should we apply |copy-asis| configuration parameter to this method?
175 wakaba 1.1
176 wakaba 1.21 return undef unless UNIVERSAL::isa ($source, 'Message::DOM::Node');
177 wakaba 1.1
178 wakaba 1.21 my $strict = $self->strict_error_checking;
179     if ($strict and $$self->{manakai_read_only}) {
180     report Message::DOM::DOMException
181     -object => $self,
182     -type => 'NO_MODIFICATION_ALLOWED_ERR',
183     -subtype => 'READ_ONLY_NODE_ERR';
184     }
185 wakaba 1.1
186 wakaba 1.21 my $parent = $source->parent_node;
187     if ($strict and defined $parent and $$parent->{manakai_read_only}) {
188     report Message::DOM::DOMException
189     -object => $self,
190     -type => 'NO_MODIFICATION_ALLOWED_ERR',
191     -subtype => 'READ_ONLY_NODE_ERR';
192     }
193 wakaba 1.1
194 wakaba 1.21 my $nt = $source->node_type;
195     my $oe;
196     if ($nt == 2) { # ATTRIBUTE_NODE
197     $oe = $source->owner_element;
198     if ($strict and defined $oe and $$oe->{manakai_read_only}) {
199     report Message::DOM::DOMException
200     -object => $self,
201     -type => 'NO_MODIFICATION_ALLOWED_ERR',
202     -subtype => 'READ_ONLY_NODE_ERR';
203     }
204     } elsif ($nt == 9 or $nt == 10 or $nt == 6 or $nt == 12 or
205     $nt == 81001 or $nt == 81002) {
206     # DOCUMENT_NODE, DOCUMENT_TYPE_NODE, ENTITY_NODE, NOTATION_NODE,
207     # ELEMENT_TYPE_DEFINITION_NODE, ATTRIBUTE_DEFINITION_NODE
208     report Message::DOM::DOMException
209     -object => $self,
210     -type => 'NOT_SUPPORTED_ERR',
211     -subtype => 'ADOPT_NODE_TYPE_NOT_SUPPORTED_ERR';
212     ## ISSUE: Define ELEMENT_TYPE_DEFINITION_NODE and ATTRIBUTE_DEFINITION_NODE
213     }
214 wakaba 1.1
215 wakaba 1.21 my @change_od;
216     my @nodes = ($source);
217     while (@nodes) {
218     my $node = shift @nodes;
219     my $nt = $node->node_type;
220     if ($strict and $$node->{manakai_read_only}) {
221     report Message::DOM::DOMException
222     -object => $self,
223     -type => 'NO_MODIFICATION_ALLOWED_ERR',
224     -subtype => 'READ_ONLY_NODE_ERR';
225 wakaba 1.1 }
226    
227 wakaba 1.21 push @change_od, $node;
228     push @nodes, @{$node->child_nodes}, @{$node->attributes or []};
229     } # @nodes
230 wakaba 1.1
231 wakaba 1.21 local $Error::Depth = $Error::Depth + 1;
232 wakaba 1.1
233 wakaba 1.21 if (defined $parent) {
234     $parent->remove_child ($source);
235     } elsif (defined $oe) {
236     $oe->remove_attribute_node ($source);
237     }
238 wakaba 1.1
239 wakaba 1.21 return $source if $self eq $change_od[0]->owner_document;
240     ## NOTE: The array must have more than zero
241     ## nodes by definition. In addition,
242     ## it cannot contain document or document
243     ## type nodes in current implementation.
244 wakaba 1.1
245 wakaba 1.21 my @ud_node;
246     for my $n (@change_od) {
247     $$n->{owner_document} = $self;
248     Scalar::Util::weaken ($$n->{owner_document});
249     if ($$n->{user_data}) {
250     push @ud_node, $n;
251     }
252     }
253 wakaba 1.1
254 wakaba 1.21 for my $src (@ud_node) {
255     my $src_ud = $$src->{user_data};
256     for my $key (keys %{$src_ud}) {
257     my $dh = $src_ud->{$key}->[1];
258     if ($dh) {
259     $dh->(5, $key, $src_ud->{$key}->[0], $src, undef); # NODE_ADOPTED
260 wakaba 1.1 }
261     }
262     }
263    
264 wakaba 1.21 return $source;
265     } # adopt_node
266    
267     sub append_child ($$) {
268     ## NOTE: Overrides |Node|'s implementation.
269     my $self = $_[0];
270 wakaba 1.1
271 wakaba 1.21 ## NOTE: |$self_od| code here in some $self->node_type.
272 wakaba 1.1
273 wakaba 1.21 ## -- Node Type check
274     my @new_child;
275     my $new_child_parent;
276     if ($_[1]->node_type == 11) { # DOCUMENT_FRAGMENT_NODE
277     push @new_child, @{$_[1]->child_nodes};
278     $new_child_parent = $_[1];
279     } else {
280     @new_child = ($_[1]);
281     $new_child_parent = $_[1]->parent_node;
282     }
283 wakaba 1.1
284 wakaba 1.21 ## NOTE: Depends on $self->node_type:
285     if ($$self->{strict_error_checking}) {
286     my $child_od = $_[1]->owner_document || $_[1]; # might be DocumentType
287     if ($self ne $child_od and $child_od->node_type != 10) {
288     report Message::DOM::DOMException # DOCUMENT_TYPE_NODE
289     -object => $self,
290     -type => 'WRONG_DOCUMENT_ERR',
291     -subtype => 'EXTERNAL_OBJECT_ERR';
292     }
293    
294     if ($$self->{manakai_read_only} or
295     (@new_child and defined $new_child_parent and
296     $$new_child_parent->{manakai_read_only})) {
297     report Message::DOM::DOMException
298     -object => $self,
299     -type => 'NO_MODIFICATION_ALLOWED_ERR',
300     -subtype => 'READ_ONLY_NODE_ERR';
301     }
302    
303     ## NOTE: Only in |Document|:
304     my $strict_children = $self->dom_config->get_parameter
305     (q<http://suika.fam.cx/www/2006/dom-config/strict-document-children>);
306     if ($strict_children) {
307     my $has_el;
308     my $has_dt;
309     my $child_nt = $_[1]->node_type;
310     if ($child_nt == 1) { # ELEMENT_NODE
311     $has_el = 1;
312     } elsif ($child_nt == 10) { # DOCUMENT_TYPE_NODE
313     $has_dt = 1;
314     } elsif ($child_nt == 11) { # DOCUMENT_FRAGMENT_NODE
315     for my $cn (@{$_[1]->child_nodes}) {
316     my $cnt = $cn->node_type;
317     if ($cnt == 1) { # ELEMENT_NODE
318     if ($has_el) {
319     report Message::DOM::DOMException
320     -object => $self,
321     -type => 'HIERARCHY_REQUEST_ERR',
322     -subtype => 'CHILD_NODE_TYPE_ERR';
323     }
324     $has_el = 1;
325     } elsif ($cnt == 10) { # DOCUMENT_TYPE_NODE
326     ## NOTE: |DocumentType| node cannot be contained in
327     ## |DocumentFragment| in strict mode.
328     if ($has_dt) {
329     report Message::DOM::DOMException
330     -object => $self,
331     -type => 'HIERARCHY_REQUEST_ERR',
332     -subtype => 'CHILD_NODE_TYPE_ERR';
333     }
334     $has_dt = 1;
335     }
336     }
337     }
338    
339     if ($has_el) {
340     my $anode = $self->last_child;
341     while (defined $anode) {
342     if ($anode->node_type == 1) { # ELEMENT_NODE
343     report Message::DOM::DOMException
344     -object => $self,
345     -type => 'HIERARCHY_REQUEST_ERR',
346     -subtype => 'CHILD_NODE_TYPE_ERR';
347     }
348     $anode = $anode->previous_sibling;
349     }
350     } # has_el
351     if ($has_dt) {
352     my $anode = $self->last_child;
353     while (defined $anode) {
354     my $ant = $anode->node_type;
355     if ($ant == 1 or $ant == 10) { # ELEMENT_NODE or DOCUMENT_TYPE_NODE
356     report Message::DOM::DOMException
357     -object => $self,
358     -type => 'HIERARCHY_REQUEST_ERR',
359     -subtype => 'CHILD_NODE_TYPE_ERR';
360     }
361     $anode = $anode->previous_sibling;
362     }
363     } # has_dt
364     }
365 wakaba 1.1
366 wakaba 1.21 for my $cn (@new_child) {
367     unless ({
368     3, (not $strict_children), # TEXT_NODE
369     5, (not $strict_children), # ENTITY_REFERENCE_NODE
370     1, 1, # ELEMENT_NODE
371     4, (not $strict_children), # CDATA_SECTION_NODE
372     7, 1, # PROCESSING_INSTRUCTION_NODE
373     8, 1, # COMMENT_NODE
374     10, 1, # DOCUMENT_TYPE_NODE
375     }->{$cn->node_type}) {
376     report Message::DOM::DOMException
377     -object => $self,
378     -type => 'HIERARCHY_REQUEST_ERR',
379     -subtype => 'CHILD_NODE_TYPE_ERR';
380     }
381     }
382 wakaba 1.1
383 wakaba 1.21 ## NOTE: Ancestor check here in |Node|.
384     }
385 wakaba 1.1
386 wakaba 1.21 ## NOTE: "Insert at" code only in insert_before and replace_child
387 wakaba 1.1
388 wakaba 1.21 ## -- Removes from parent
389     if ($new_child_parent) {
390     if (@new_child == 1) {
391     my $v = $$new_child_parent->{child_nodes};
392     RP: for my $i (0..$#$v) {
393     if ($v->[$i] eq $new_child[0]) {
394     splice @$v, $i, 1, ();
395     last RP;
396     }
397     } # RP
398     } else {
399     @{$$new_child_parent->{child_nodes}} = ();
400     }
401     }
402 wakaba 1.1
403 wakaba 1.21 ## -- Rewrite the |parentNode| properties
404     for my $nc (@new_child) {
405     $$nc->{parent_node} = $self;
406     Scalar::Util::weaken ($$nc->{parent_node});
407     }
408 wakaba 1.1
409 wakaba 1.21 ## NOTE: Depends on method:
410     push @{$$self->{child_nodes}}, @new_child;
411 wakaba 1.1
412 wakaba 1.21 ## NOTE: Only in |Document|.
413     for (@new_child) {
414     delete $$_->{implementation};
415     $$_->{owner_document} = $self;
416     Scalar::Util::weaken ($$_->{owner_document});
417     }
418 wakaba 1.1
419 wakaba 1.21 return $_[1];
420     } # apepnd_child
421 wakaba 1.1
422 wakaba 1.21 sub manakai_append_text ($$) {
423     my $self = shift;
424     if ($$self->{'http://suika.fam.cx/www/2006/dom-config/strict-document-children'}) {
425     #
426     } else {
427     local $Error::Depth = $Error::Depth + 1;
428     return $self->SUPER::manakai_append_text (@_);
429     }
430     } # manakai_append_text
431 wakaba 1.1
432 wakaba 1.21 sub insert_before ($$) {
433     ## NOTE: Overrides |Node|'s implementation.
434     my $self = $_[0];
435 wakaba 1.1
436 wakaba 1.21 ## NOTE: |$self_od| code here depending on $self->node_type.
437 wakaba 1.1
438 wakaba 1.21 ## -- Node Type check
439     my @new_child;
440     my $new_child_parent;
441     if ($_[1]->node_type == 11) { # DOCUMENT_FRAGMENT_NODE
442     push @new_child, @{$_[1]->child_nodes};
443     $new_child_parent = $_[1];
444     } else {
445     @new_child = ($_[1]);
446     $new_child_parent = $_[1]->parent_node;
447     }
448 wakaba 1.1
449 wakaba 1.21 ## NOTE: Depends on $self->node_type:
450     if ($$self->{strict_error_checking}) {
451     my $child_od = $_[1]->owner_document || $_[1]; # might be DocumentType
452     if ($self ne $child_od and $child_od->node_type != 10) {
453     report Message::DOM::DOMException # DOCUMENT_TYPE_NODE
454     -object => $self,
455     -type => 'WRONG_DOCUMENT_ERR',
456     -subtype => 'EXTERNAL_OBJECT_ERR';
457     }
458    
459     if ($$self->{manakai_read_only} or
460     (@new_child and defined $new_child_parent and
461     $$new_child_parent->{manakai_read_only})) {
462     report Message::DOM::DOMException
463     -object => $self,
464     -type => 'NO_MODIFICATION_ALLOWED_ERR',
465     -subtype => 'READ_ONLY_NODE_ERR';
466     }
467    
468     ## NOTE: Only in |Document|:
469     my $strict_children = $self->dom_config->get_parameter
470     (q<http://suika.fam.cx/www/2006/dom-config/strict-document-children>);
471     if ($strict_children) {
472     my $has_el;
473     my $has_dt;
474     my $child_nt = $_[1]->node_type;
475     if ($child_nt == 1) { # ELEMENT_NODE
476     $has_el = 1;
477     } elsif ($child_nt == 10) { # DOCUMENT_TYPE_NODE
478     $has_dt = 1;
479     } elsif ($child_nt == 11) { # DOCUMENT_FRAGMENT_NODE
480     for my $cn (@{$_[1]->child_nodes}) {
481     my $cnt = $cn->node_type;
482     if ($cnt == 1) { # ELEMENT_NODE
483     if ($has_el) {
484     report Message::DOM::DOMException
485     -object => $self,
486     -type => 'HIERARCHY_REQUEST_ERR',
487     -subtype => 'CHILD_NODE_TYPE_ERR';
488     }
489     $has_el = 1;
490     } elsif ($cnt == 10) { # DOCUMENT_TYPE_NODE
491     ## NOTE: |DocumentType| node cannot be contained in
492     ## |DocumentFragment| in strict mode.
493     if ($has_dt) {
494     report Message::DOM::DOMException
495     -object => $self,
496     -type => 'HIERARCHY_REQUEST_ERR',
497     -subtype => 'CHILD_NODE_TYPE_ERR';
498     }
499     $has_dt = 1;
500     }
501     }
502 wakaba 1.1 }
503    
504 wakaba 1.21 ## ISSUE: This code is wrong. Old manakai's implementation
505     ## is better, but it is also wrong in some edge cases.
506     ## Maybe we should remove these code entirely. DOM3Core
507     ## conformance is not important for this bit. It only makes
508     ## things too complex. Same for replace_child's code.
509     if ($has_el) {
510     my $anode = $self->last_child;
511     while (defined $anode) {
512     if ($anode->node_type == 1) { # ELEMENT_NODE
513     report Message::DOM::DOMException
514     -object => $self,
515     -type => 'HIERARCHY_REQUEST_ERR',
516     -subtype => 'CHILD_NODE_TYPE_ERR';
517 wakaba 1.1 }
518 wakaba 1.21 $anode = $anode->previous_sibling;
519 wakaba 1.1 }
520 wakaba 1.21 } # has_el
521     if ($has_dt) {
522     my $anode = $self->last_child;
523     while (defined $anode) {
524     my $ant = $anode->node_type;
525     if ($ant == 1 or $ant == 10) { # ELEMENT_NODE or DOCUMENT_TYPE_NODE
526     report Message::DOM::DOMException
527     -object => $self,
528     -type => 'HIERARCHY_REQUEST_ERR',
529     -subtype => 'CHILD_NODE_TYPE_ERR';
530     }
531     $anode = $anode->previous_sibling;
532     }
533     } # has_dt
534     }
535 wakaba 1.1
536 wakaba 1.21 for my $cn (@new_child) {
537     unless ({
538     3, (not $strict_children), # TEXT_NODE
539     5, (not $strict_children), # ENTITY_REFERENCE_NODE
540     1, 1, # ELEMENT_NODE
541     4, (not $strict_children), # CDATA_SECTION_NODE
542     7, 1, # PROCESSING_INSTRUCTION_NODE
543     8, 1, # COMMENT_NODE
544     10, 1, # DOCUMENT_TYPE_NODE
545     }->{$cn->node_type}) {
546     report Message::DOM::DOMException
547     -object => $self,
548     -type => 'HIERARCHY_REQUEST_ERR',
549     -subtype => 'CHILD_NODE_TYPE_ERR';
550     }
551     }
552 wakaba 1.1
553 wakaba 1.21 ## NOTE: Ancestor check here in |Node|.
554     }
555    
556     ## -- Insert at... ## NOTE: Only in insert_before and replace_child
557     my $index = -1; # last
558     if (defined $_[2]) {
559     ## error if $_[1] eq $_[2];
560    
561     my $cns = $self->child_nodes;
562     my $cnsl = @$cns;
563     C: {
564     $index = 0;
565     for my $i (0..($cnsl-1)) {
566     my $cn = $cns->[$i];
567     if ($cn eq $_[2]) {
568     $index += $i;
569     last C;
570     } elsif ($cn eq $_[1]) {
571     $index = -1; # offset
572     }
573     }
574 wakaba 1.1
575 wakaba 1.21 report Message::DOM::DOMException
576     -object => $self,
577     -type => 'NOT_FOUND_ERR',
578     -subtype => 'NOT_CHILD_ERR';
579     } # C
580     }
581     ## NOTE: "else" only in replace_child
582 wakaba 1.1
583 wakaba 1.21 ## -- Removes from parent
584     if ($new_child_parent) {
585     if (@new_child == 1) {
586     my $v = $$new_child_parent->{child_nodes};
587     RP: for my $i (0..$#$v) {
588     if ($v->[$i] eq $new_child[0]) {
589     splice @$v, $i, 1, ();
590     last RP;
591     }
592     } # RP
593     } else {
594     @{$$new_child_parent->{child_nodes}} = ();
595     }
596     }
597 wakaba 1.1
598 wakaba 1.21 ## -- Rewrite the |parentNode| properties
599     for my $nc (@new_child) {
600     $$nc->{parent_node} = $self;
601     Scalar::Util::weaken ($$nc->{parent_node});
602     }
603 wakaba 1.1
604 wakaba 1.21 ## NOTE: Depends on method:
605     if ($index == -1) {
606     push @{$$self->{child_nodes}}, @new_child;
607     } else {
608     splice @{$$self->{child_nodes}}, $index, 0, @new_child;
609     }
610 wakaba 1.1
611 wakaba 1.21 ## NOTE: Only in |Document|.
612     for (@new_child) {
613     delete $$_->{implementation};
614     $$_->{owner_document} = $self;
615     Scalar::Util::weaken ($$_->{owner_document});
616     }
617 wakaba 1.1
618 wakaba 1.21 return $_[1];
619     } # insert_before
620 wakaba 1.1
621 wakaba 1.21 sub replace_child ($$) {
622     ## NOTE: Overrides |Node|'s implementation.
623     my $self = $_[0];
624 wakaba 1.1
625 wakaba 1.21 ## NOTE: |$self_od| code here depending on $self->node_type.
626 wakaba 1.1
627 wakaba 1.21 ## -- Node Type check
628     my @new_child;
629     my $new_child_parent;
630     if ($_[1]->node_type == 11) { # DOCUMENT_FRAGMENT_NODE
631     push @new_child, @{$_[1]->child_nodes};
632     $new_child_parent = $_[1];
633     } else {
634     @new_child = ($_[1]);
635     $new_child_parent = $_[1]->parent_node;
636     }
637 wakaba 1.1
638 wakaba 1.21 ## NOTE: Depends on $self->node_type:
639     if ($$self->{strict_error_checking}) {
640     my $child_od = $_[1]->owner_document || $_[1]; # might be DocumentType
641     if ($self ne $child_od and $child_od->node_type != 10) {
642     report Message::DOM::DOMException # DOCUMENT_TYPE_NODE
643     -object => $self,
644     -type => 'WRONG_DOCUMENT_ERR',
645     -subtype => 'EXTERNAL_OBJECT_ERR';
646     }
647    
648     if ($$self->{manakai_read_only} or
649     (@new_child and defined $new_child_parent and
650     $$new_child_parent->{manakai_read_only})) {
651     report Message::DOM::DOMException
652     -object => $self,
653     -type => 'NO_MODIFICATION_ALLOWED_ERR',
654     -subtype => 'READ_ONLY_NODE_ERR';
655     }
656    
657     ## NOTE: Only in |Document|:
658     my $strict_children = $self->dom_config->get_parameter
659     (q<http://suika.fam.cx/www/2006/dom-config/strict-document-children>);
660     if ($strict_children) {
661     my $has_el;
662     my $has_dt;
663     my $child_nt = $_[1]->node_type;
664     if ($child_nt == 1) { # ELEMENT_NODE
665     $has_el = 1;
666     } elsif ($child_nt == 10) { # DOCUMENT_TYPE_NODE
667     $has_dt = 1;
668     } elsif ($child_nt == 11) { # DOCUMENT_FRAGMENT_NODE
669     for my $cn (@{$_[1]->child_nodes}) {
670     my $cnt = $cn->node_type;
671     if ($cnt == 1) { # ELEMENT_NODE
672     if ($has_el) {
673     report Message::DOM::DOMException
674     -object => $self,
675     -type => 'HIERARCHY_REQUEST_ERR',
676     -subtype => 'CHILD_NODE_TYPE_ERR';
677     }
678     $has_el = 1;
679     } elsif ($cnt == 10) { # DOCUMENT_TYPE_NODE
680     ## NOTE: |DocumentType| node cannot be contained in
681     ## |DocumentFragment| in strict mode.
682     if ($has_dt) {
683     report Message::DOM::DOMException
684     -object => $self,
685     -type => 'HIERARCHY_REQUEST_ERR',
686     -subtype => 'CHILD_NODE_TYPE_ERR';
687     }
688     $has_dt = 1;
689     }
690     }
691     }
692    
693     if ($has_el) {
694     my $anode = $self->last_child;
695     while (defined $anode) {
696     if ($anode->node_type == 1) { # ELEMENT_NODE
697     report Message::DOM::DOMException
698     -object => $self,
699     -type => 'HIERARCHY_REQUEST_ERR',
700     -subtype => 'CHILD_NODE_TYPE_ERR';
701     }
702     $anode = $anode->previous_sibling;
703     }
704     } # has_el
705     if ($has_dt) {
706     my $anode = $self->last_child;
707     while (defined $anode) {
708     my $ant = $anode->node_type;
709     if ($ant == 1 or $ant == 10) { # ELEMENT_NODE or DOCUMENT_TYPE_NODE
710     report Message::DOM::DOMException
711     -object => $self,
712     -type => 'HIERARCHY_REQUEST_ERR',
713     -subtype => 'CHILD_NODE_TYPE_ERR';
714     }
715     $anode = $anode->previous_sibling;
716     }
717     } # has_dt
718     }
719 wakaba 1.1
720 wakaba 1.21 for my $cn (@new_child) {
721     unless ({
722     3, (not $strict_children), # TEXT_NODE
723     5, (not $strict_children), # ENTITY_REFERENCE_NODE
724     1, 1, # ELEMENT_NODE
725     4, (not $strict_children), # CDATA_SECTION_NODE
726     7, 1, # PROCESSING_INSTRUCTION_NODE
727     8, 1, # COMMENT_NODE
728     10, 1, # DOCUMENT_TYPE_NODE
729     }->{$cn->node_type}) {
730     report Message::DOM::DOMException
731     -object => $self,
732     -type => 'HIERARCHY_REQUEST_ERR',
733     -subtype => 'CHILD_NODE_TYPE_ERR';
734     }
735     }
736 wakaba 1.1
737 wakaba 1.21 ## NOTE: Ancestor check here in |Node|.
738     }
739    
740     ## -- Insert at... ## NOTE: Only in insertBefore and replaceChild
741     my $index = -1; # last
742     if (defined $_[2]) {
743     ## error if $_[1] eq $_[2];
744    
745     my $cns = $self->child_nodes;
746     my $cnsl = @$cns;
747     C: {
748     $index = 0;
749     for my $i (0..($cnsl-1)) {
750     my $cn = $cns->[$i];
751     if ($cn eq $_[2]) {
752     $index += $i;
753     last C;
754     } elsif ($cn eq $_[1]) {
755     $index = -1; # offset
756     }
757     }
758 wakaba 1.1
759 wakaba 1.21 report Message::DOM::DOMException
760     -object => $self,
761     -type => 'NOT_FOUND_ERR',
762     -subtype => 'NOT_CHILD_ERR';
763     } # C
764     } else {
765     ## NOTE: Only in replaceChild
766     report Message::DOM::DOMException
767     -object => $self,
768     -type => 'NOT_FOUND_ERR',
769     -subtype => 'NOT_CHILD_ERR';
770     }
771 wakaba 1.1
772     ## -- Removes from parent
773 wakaba 1.21 if ($new_child_parent) {
774     if (@new_child == 1) {
775     my $v = $$new_child_parent->{child_nodes};
776 wakaba 1.1 RP: for my $i (0..$#$v) {
777 wakaba 1.13 if ($v->[$i] eq $new_child[0]) {
778 wakaba 1.1 splice @$v, $i, 1, ();
779     last RP;
780     }
781     } # RP
782 wakaba 1.21 } else {
783     @{$$new_child_parent->{child_nodes}} = ();
784 wakaba 1.1 }
785     }
786    
787     ## -- Rewrite the |parentNode| properties
788     for my $nc (@new_child) {
789 wakaba 1.21 $$nc->{parent_node} = $self;
790     Scalar::Util::weaken ($$nc->{parent_node});
791 wakaba 1.13 }
792 wakaba 1.1
793 wakaba 1.21 ## NOTE: Depends on method:
794     splice @{$$self->{child_nodes}}, $index, 1, @new_child;
795     delete ${$_[2]}->{parent_node};
796 wakaba 1.1
797 wakaba 1.21 ## NOTE: Only in |Document|.
798     for (@new_child) {
799     delete $$_->{implementation};
800     $$_->{owner_document} = $self;
801     Scalar::Util::weaken ($$_->{owner_document});
802     }
803    
804     return $_[2];
805     } # replace_child
806 wakaba 1.1
807 wakaba 1.21 ## |Document| attributes
808 wakaba 1.1
809 wakaba 1.21 ## NOTE: A manakai extension.
810     sub all_declarations_processed ($;$);
811 wakaba 1.1
812 wakaba 1.21 sub doctype ($) {
813     my $self = $_[0];
814     for (@{$self->child_nodes}) {
815     if ($_->node_type == 10) { # DOCUMENT_TYPE_NODE
816     return $_;
817     }
818     }
819     return undef;
820     } # doctype
821 wakaba 1.1
822 wakaba 1.21 sub document_element ($) {
823     my $self = shift;
824     for (@{$self->child_nodes}) {
825     if ($_->node_type == 1) { # ELEMENT_NODE
826     return $_;
827     }
828     }
829     return undef;
830     } # document_element
831 wakaba 1.1
832 wakaba 1.21 sub document_uri ($;$);
833 wakaba 1.1
834 wakaba 1.21 sub dom_config ($) {
835     require Message::DOM::DOMConfiguration;
836     return bless \\($_[0]), 'Message::DOM::DOMConfiguration';
837     } # dom_config
838 wakaba 1.1
839 wakaba 1.21 sub manakai_entity_base_uri ($;$) {
840     my $self = $_[0];
841     if (@_ > 1) {
842     if ($$self->{strict_error_checking}) {
843     if ($$self->{manakai_read_only}) {
844     report Message::DOM::DOMException
845     -object => $self,
846     -type => 'NO_MODIFICATION_ALLOWED_ERR',
847     -subtype => 'READ_ONLY_NODE_ERR';
848     }
849     }
850     if (defined $_[1]) {
851     $$self->{manakai_entity_base_uri} = ''.$_[1];
852     } else {
853     delete $$self->{manakai_entity_base_uri};
854     }
855     }
856 wakaba 1.1
857 wakaba 1.21 if (defined $$self->{manakai_entity_base_uri}) {
858     return $$self->{manakai_entity_base_uri};
859     } else {
860     return $$self->{document_uri};
861     }
862     } # manakai_entity_base_uri
863 wakaba 1.1
864 wakaba 1.21 sub input_encoding ($;$);
865 wakaba 1.1
866 wakaba 1.21 sub strict_error_checking ($;$) {
867     ## NOTE: Same as trivial boolean accessor, except no read-only checking.
868     if (@_ > 1) {
869     if ($_[1]) {
870     ${$_[0]}->{strict_error_checking} = 1;
871     } else {
872     delete ${$_[0]}->{strict_error_checking};
873     }
874     }
875     return ${$_[0]}->{strict_error_checking};
876     } # strict_error_checking
877 wakaba 1.1
878 wakaba 1.21 ## ISSUE: Setting manakai_is_html true shadows
879     ## xml_* properties. Is this desired?
880 wakaba 1.1
881 wakaba 1.21 sub xml_encoding ($;$) {
882     my $self = $_[0];
883     if (@_ > 1) {
884     ## NOTE: A manakai extension.
885     if ($$self->{strict_error_checking}) {
886     if ($$self->{manakai_is_html}) {
887     report Message::DOM::DOMException
888     -object => $self,
889     -type => 'NOT_SUPPORTED_ERR',
890     -subtype => 'NON_HTML_OPERATION_ERR';
891     }
892     if ($$self->{manakai_read_only}) {
893     report Message::DOM::DOMException
894     -object => $self,
895     -type => 'NO_MODIFICATION_ALLOWED_ERR',
896     -subtype => 'READ_ONLY_NODE_ERR';
897     }
898     }
899     if (defined $_[1]) {
900     $$self->{xml_encoding} = ''.$_[1];
901     } else {
902     delete $$self->{xml_encoding};
903     }
904     }
905    
906     if ($$self->{manakai_is_html}) {
907     return undef;
908     } else {
909     return $$self->{xml_encoding};
910     }
911     } # xml_encoding
912 wakaba 1.1
913 wakaba 1.21 sub xml_standalone ($;$) {
914     my $self = $_[0];
915     if (@_ > 1) {
916     if ($$self->{strict_error_checking}) {
917     if ($$self->{manakai_is_html}) {
918     report Message::DOM::DOMException
919     -object => $self,
920     -type => 'NOT_SUPPORTED_ERR',
921     -subtype => 'NON_HTML_OPERATION_ERR';
922     }
923     ## NOTE: Not in DOM3.
924     if ($$self->{manakai_read_only}) {
925     report Message::DOM::DOMException
926     -object => $self,
927     -type => 'NO_MODIFICATION_ALLOWED_ERR',
928     -subtype => 'READ_ONLY_NODE_ERR';
929     }
930     }
931     if ($_[1]) {
932     $$self->{xml_standalone} = 1;
933     } else {
934     delete $$self->{xml_standalone};
935     }
936     }
937    
938     if ($$self->{manakai_is_html}) {
939     return 0;
940     } else {
941     return $$self->{xml_standalone};
942     }
943     } # xml_standalone
944 wakaba 1.1
945 wakaba 1.21 sub xml_version ($;$) {
946     my $self = $_[0];
947     if (@_ > 1) {
948     my $v = ''.$_[1];
949     if ($$self->{strict_error_checking}) {
950     if ($$self->{manakai_is_html}) {
951     report Message::DOM::DOMException
952     -object => $self,
953     -type => 'NOT_SUPPORTED_ERR',
954     -subtype => 'NON_HTML_OPERATION_ERR';
955     }
956     if ($v ne '1.0' and $v ne '1.1') {
957     report Message::DOM::DOMException
958     -object => $self,
959     -type => 'NOT_SUPPORTED_ERR',
960     -subtype => 'UNKNOWN_XML_VERSION_ERR';
961     }
962     if ($$self->{manakai_read_only}) {
963     ## ISSUE: Not in DOM3.
964     report Message::DOM::DOMException
965     -object => $self,
966     -type => 'NO_MODIFICATION_ALLOWED_ERR',
967     -subtype => 'READ_ONLY_NODE_ERR';
968     }
969     }
970     $$self->{xml_version} = $v;
971     }
972    
973     if (defined wantarray) {
974     if ($$self->{manakai_is_html}) {
975     return undef;
976     } elsif (defined $$self->{xml_version}) {
977     return $$self->{xml_version};
978     } else {
979     return '1.0';
980     }
981     }
982     } # xml_version
983 wakaba 1.1
984 wakaba 1.21 ## |Document| methods
985 wakaba 1.1
986 wakaba 1.21 sub get_element_by_id ($$) {
987     local $Error::Depth = $Error::Depth + 1;
988     my @nodes = @{$_[0]->child_nodes};
989     N: while (@nodes) {
990     my $node = shift @nodes;
991     next N unless $node->node_type == 1; # ELEMENT_NODE
992     for my $attr (@{$node->attributes}) {
993     if ($attr->is_id and $attr->value eq $_[1]) {
994     return $node;
995     }
996     }
997     unshift @nodes, @{$node->child_nodes};
998     } # N
999     return undef;
1000     } # get_element_by_id
1001 wakaba 1.1
1002 wakaba 1.21 ## TODO: HTML5 case normalization
1003     sub get_elements_by_tag_name ($$) {
1004     my $name = ''.$_[1];
1005     my $chk;
1006     if ($name eq '*') {
1007     $chk = sub () { 1 };
1008     } else {
1009     $chk = sub ($) {
1010     return $_[0]->manakai_tag_name eq $name;
1011     };
1012     }
1013 wakaba 1.1
1014 wakaba 1.21 require Message::DOM::NodeList;
1015     return bless \[$_[0], $chk], 'Message::DOM::NodeList::GetElementsList';
1016     } # get_elements_by_tag_name
1017 wakaba 1.1
1018 wakaba 1.21 sub get_elements_by_tag_name_ns ($$$) {
1019     my $nsuri = defined $_[1] ? ''.$_[1] : '';
1020     my $lname = ''.$_[2];
1021     my $chk;
1022     if ($nsuri eq '*') {
1023     if ($lname eq '*') {
1024     $chk = sub () { 1 };
1025     } else {
1026     $chk = sub ($) {
1027     return $_[0]->manakai_local_name eq $lname;
1028     };
1029     }
1030     } elsif ($nsuri eq '') {
1031     if ($lname eq '*') {
1032     $chk = sub ($) {
1033     return not defined $_[0]->namespace_uri;
1034     };
1035     } else {
1036     $chk = sub ($) {
1037     return (not defined $_[0]->namespace_uri and
1038     $_[0]->manakai_local_name eq $lname);
1039     };
1040     }
1041     } else {
1042     if ($lname eq '*') {
1043     $chk = sub ($) {
1044     my $ns = $_[0]->namespace_uri;
1045     return (defined $ns and $ns eq $nsuri);
1046     };
1047     } else {
1048     $chk = sub ($) {
1049     my $ns = $_[0]->namespace_uri;
1050     return (defined $ns and $ns eq $nsuri and
1051     $_[0]->manakai_local_name eq $lname);
1052     };
1053     }
1054     }
1055 wakaba 1.1
1056 wakaba 1.21 require Message::DOM::NodeList;
1057     return bless \[$_[0], $chk], 'Message::DOM::NodeList::GetElementsList';
1058     } # get_elements_by_tag_name
1059 wakaba 1.1
1060 wakaba 1.21 ## TODO: import_node
1061 wakaba 1.1
1062 wakaba 1.21 ## TODO: normalize_document
1063 wakaba 1.1
1064 wakaba 1.21 ## TODO: rename_node
1065 wakaba 1.1
1066 wakaba 1.21 ## |DocumentTraversal| methods
1067 wakaba 1.1
1068 wakaba 1.21 ## TODO: create_node_iterator
1069 wakaba 1.1
1070 wakaba 1.21 sub manakai_create_serial_walker ($$;$$$);
1071 wakaba 1.1
1072 wakaba 1.21 sub create_tree_walker ($$;$$$);
1073 wakaba 1.1
1074 wakaba 1.21 ## |HTMLDocument| attributes
1075 wakaba 1.1
1076 wakaba 1.21 sub compat_mode ($) {
1077     if (${$_[0]}->{manakai_is_html}) {
1078     if (defined ${$_[0]}->{manakai_compat_mode} and
1079     ${$_[0]}->{manakai_compat_mode} eq 'quirks') {
1080     return 'BackCompat';
1081     }
1082     }
1083     return 'CSS1Compat';
1084     } # compat_mode
1085 wakaba 1.1
1086 wakaba 1.21 sub manakai_compat_mode ($;$) {
1087     if (${$_[0]}->{manakai_is_html}) {
1088     if (@_ > 1 and defined $_[1] and
1089     {'no quirks' => 1, 'limited quirks' => 1, 'quirks' => 1}->{$_[1]}) {
1090     ${$_[0]}->{manakai_compat_mode} = $_[1];
1091     }
1092     return ${$_[0]}->{manakai_compat_mode} || 'no quirks';
1093 wakaba 1.1 } else {
1094 wakaba 1.21 return 'no quirks';
1095 wakaba 1.1 }
1096 wakaba 1.21 } # manakai_compat_mode
1097 wakaba 1.1
1098 wakaba 1.21 sub inner_html ($;$) {
1099     my $self = $_[0];
1100     local $Error::Depth = $Error::Depth + 1;
1101    
1102     if ($$self->{manakai_is_html}) {
1103     require Whatpm::HTML;
1104     if (@_ > 1) {
1105     ## Step 1
1106     ## TODO: Stop parsing and ...
1107    
1108     ## Step 2
1109     my @cn = @{$self->child_nodes};
1110     for (@cn) { ## NOTE: Might throw a |NO_MODIFICATION_ALLOWED_ERR|.
1111     $self->remove_child ($_); #
1112     }
1113 wakaba 1.1
1114 wakaba 1.21 ## Step 3, 4, 5
1115     Whatpm::HTML->parse_string ($_[1] => $self);
1116 wakaba 1.1
1117 wakaba 1.21 ## TODO:
1118     ## <script>var input = function_to_do_xmlhttprequest (location.href);
1119     ## document.innerHTML = input</script>
1120 wakaba 1.1
1121 wakaba 1.21 return unless defined wantarray;
1122     }
1123 wakaba 1.1
1124 wakaba 1.21 return ${ Whatpm::HTML->get_inner_html ($self) };
1125     } else {
1126     if (@_ > 1) {
1127     ## Step 1
1128     require Whatpm::XMLParser; # MUST
1129     my $doc = $self->implementation->create_document;
1130    
1131     ## Step 2
1132     #
1133 wakaba 1.1
1134 wakaba 1.21 ## Step 3
1135     $doc = Whatpm::XMLParser->parse_string ($_[1] => $doc); # MUST
1136 wakaba 1.1
1137 wakaba 1.21 ## Step 4
1138     #
1139 wakaba 1.1
1140 wakaba 1.21 ## Step 5
1141     ## TODO: ill-formed -> SYNTAX_ERR # MUST
1142 wakaba 1.1
1143 wakaba 1.21 ## Step 6 # MUST
1144     my @cn = @{$self->child_nodes}; ## TODO: If read-only
1145     for (@cn) {
1146     $self->remove_child ($_);
1147     }
1148 wakaba 1.1
1149 wakaba 1.21 ## Step 7, 8, 9, 10
1150     for my $node (@{$doc->child_nodes}) {
1151     $self->append_child ($self->adopt_node ($node));
1152     }
1153 wakaba 1.1
1154 wakaba 1.21 return unless defined wantarray;
1155     }
1156 wakaba 1.1
1157 wakaba 1.21 ## TODO: This serializer is currently not conformant to HTML5 spec.
1158     require Whatpm::XMLSerializer;
1159     my $r = '';
1160     for (@{$self->child_nodes}) {
1161     $r .= ${ Whatpm::XMLSerializer->get_outer_xml ($_, sub {
1162     ## TODO: INVALID_STATE_ERR
1163     }) };
1164     }
1165     return $r;
1166     }
1167     } # inner_html
1168 wakaba 1.1
1169 wakaba 1.21 sub manakai_is_html ($;$) {
1170     if (@_ > 1) {
1171     if ($_[1]) {
1172     ${$_[0]}->{manakai_is_html} = 1;
1173     } else {
1174     delete ${$_[0]}->{manakai_is_html};
1175     delete ${$_[0]}->{manakai_compat_mode};
1176     }
1177     }
1178     return ${$_[0]}->{manakai_is_html};
1179     } # manakai_is_html
1180 wakaba 1.1
1181 wakaba 1.21 package Message::IF::Document;
1182     package Message::IF::DocumentTraversal;
1183     package Message::IF::DocumentXDoctype;
1184     package Message::IF::HTMLDocument;
1185 wakaba 1.1
1186 wakaba 1.21 package Message::DOM::DOMImplementation;
1187 wakaba 1.1
1188 wakaba 1.21 sub create_document ($;$$$) {
1189     my $r = Message::DOM::Document->____new ($_[0]);
1190 wakaba 1.1
1191 wakaba 1.21 if (defined $_[2]) {
1192     local $Error::Depth = $Error::Depth + 1;
1193     $r->append_child ($r->create_element_ns ($_[1], $_[2])); # NAMESPACE_ERR
1194     ## NOTE: manakai might raise DOMExceptions in cases not defined
1195     ## in DOM3Core spec: XMLNSPREFIX_NONXMLNSNS_ERR,
1196     ## XMLNS_NONXMLNSNS_ERR, and NONXMLNSPREFIX_XMLNSNS_ERR.
1197     } elsif (defined $_[1]) {
1198     report Message::DOM::DOMException
1199     -object => $_[0],
1200     -type => 'NAMESPACE_ERR',
1201     -subtype => 'QNAME_NULLNS_ERR';
1202     }
1203 wakaba 1.1
1204 wakaba 1.21 if (defined $_[3]) {
1205     if ($_[3]->parent_node) {
1206     report Message::DOM::DOMException
1207     -object => $_[0],
1208     -type => 'WRONG_DOCUMENT_ERR',
1209     -subtype => 'INUSE_DOCTYPE_ERR';
1210     }
1211     local $Error::Depth = $Error::Depth + 1;
1212     $r->insert_before ($_[3], $r->first_child); # EXTERNAL_OBJECT_ERR
1213     }
1214 wakaba 1.1
1215 wakaba 1.21 return $r;
1216     } # create_document
1217 wakaba 1.1
1218 wakaba 1.21 =head1 LICENSE
1219 wakaba 1.1
1220 wakaba 1.21 Copyright 2007 Wakaba <w@suika.fam.cx>
1221 wakaba 1.1
1222 wakaba 1.21 This program is free software; you can redistribute it and/or
1223     modify it under the same terms as Perl itself.
1224 wakaba 1.1
1225 wakaba 1.21 =cut
1226 wakaba 1.1
1227     1;
1228 wakaba 1.21 ## $Date: 2007/07/29 06:46:25 $

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24